openresty使用redis作本地缓存
一,为什么要使用redis作本地缓存?
1,使用缓存通常会有三层
当使用openresty作为web服务器时,我们更看重是的它可以通过lua编程的扩展能力,就openresty而言,它可以实现的功能非常多,
提高响应速度是web服务中非常重要的功能,
使用缓存通常会有三层:
本地缓存:存在于本地机器上,直接通过nginx访问,避免网络io;
redis cluster:存储更多的供lua访问的数据,也是通过nginx访问直接返回,相比前一层缓存,增加了网络io,但仍然避免了对业务系统的访问;
业务缓存:供运行在tomcat/php-fpm/go http中内的业务代码访问。
可以比较得到本地缓存是响应速度最快的,通常可以在10ms内对请求进行响应。
我们看到的很多经过优化的BAT等大厂的站点都能在极短时间内响应请求,就是经过了层层优化的结果。
2,这里会提供一个例子:使用redis做商品详情页的cache:
流程:当用户访问时,
先从redis中获取cache内容,
如果redis中不存在此value,则会改为访问后端业务系统获取cache
说明:在生产环境中,为方便更新,通常会采用redis的主从架构,
每台业务nginx上所配备的redis的数据能得到实时更新
说明:刘宏缔的架构森林是一个专注架构的博客
网站:https://blog.imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/05/13/openresty-shi-yong-redis-zuo-ben-di-huan-cun-openresty11582/
对应的源码可以访问这里获取: https://github.com/liuhongdi/
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,nginx的配置文件:
upstream backenditem { server 127.0.0.1:8000; } server { listen 8000; server_name 8000.test.com; location / { default_type 'text/html'; content_by_lua_block {ngx.say("hello world,this is path backend from 8000:uri:"..ngx.var.request_uri)} } } server { listen 82; server_name test.com; location ~ /backenditem/(.*) { rewrite /backenditem(/.*) $1 break; proxy_next_upstream error timeout; proxy_pass http://backenditem; } location /item { default_type text/html; content_by_lua_file /data/luacache/webroot/item_redis_cache.lua; } location / { default_type 'text/html'; content_by_lua_block {ngx.say("default path:uri:"..ngx.var.request_uri)} } }
说明:1,端口8000的server是一个demo,生产环境中,它应该是使用tomcat/php-fpm/django之类的业务系统
2,location ~ /backenditem/(.*) :负责upstream到后端业务系统,
注意这里要做一次 rewrite /backenditem(/.*) $1 break; ,作用是去掉用来标识要跳转到后端的backenditem字串
3,content_by_lua_file 此处用绝对路径指定了lua代码的程序文件
三,lua程序文件: item_redis_cache.lua
--指定要访问的lua包所在的路径 package.path = package.path..";/data/luacache/webroot/config/?.lua;/data/luacache/webroot/lib/?.lua" local config = require "config_constant" local readhttp = require "read_http" local returnjson = require "return_json" --redis连接池工厂 local redis_factory = require('redis_factory')(config.redisConfig) --获取redis的连接实例 local ok, redis_a = redis_factory:spawn('redis_a') --用于接收前端数据的对象 local args=nil --获取前端的请求方式 并获取传递的参数 local request_method = ngx.var.request_method --判断是get请求还是post请求并分别拿出相应的数据 if "GET" == request_method then args = ngx.req.get_uri_args() elseif "POST" == request_method then ngx.req.read_body() args = ngx.req.get_post_args() --兼容请求使用post请求,但是传参以get方式传造成的无法获取到数据的bug if (args == nil or args.data == null) then args = ngx.req.get_uri_args() end end --ngx.log(ngx.ERR,"args.key:",args.key) if args.itemid == nil or args.itemid=="" then local json = returnjson.getjson("1",'key not exist or key is empty',"") --ngx.log(ngx.ERR,"json:",json) ngx.say(json) else --获取前端传递的itemid local itemid = args.itemid --在redis中获取itemid对应的值 local va = redis_a:get(itemid) if va == ngx.null or va == nil then --ngx.log(ngx.ERR, "redis not found content, back to http, itemid : ", itemid) local url="/backenditem/item" va = readhttp.read(url,itemid) ngx.print(returnjson.getjson(0,itemid,va)) else --响应前端 ngx.say(returnjson.getjson(0,itemid,va)) end end
四,lua访问redis的配置文件: config_constant.lua
config = {} config.redisConfig = { redis_a = { -- your connection name --ip host = '127.0.0.1', --端口 port = 6379, --密码 pass = '', --超时时间,如果是测试环境debug的话,这个值可以给长一点;如果是正式环境,可以设置为200 timeout = 120000, --redis的库 database = 0, }, } return config
五,lua程序文件:read_http.lua:用来从后端业务系统得到response
local read_http = {} function read_http.read(url,id) local resp = ngx.location.capture(url, { method = ngx.HTTP_GET, args = {id = id} }) if not resp then ngx.log(ngx.ERR, "request error :", err) return end if resp.status ~= 200 then ngx.log(ngx.ERR, "request error, status :", resp.status) return end return resp.body end return read_http
六,lua程序:return_json.lua :返回json字串
local return_json = {} function return_json.getjson(status,msg,data) local json = '{"status":"'..status..'","msg":"'..msg..'","data":"'..data..'"}' return json end return return_json
七,此项目的github地址:
https://github.com/liuhongdi/luacache
八,测试效果:
1,当有商品存在于redis中的返回 :如图
2,当商品不存在于redis中的返回: 如图
3,当参数错误时的返回 :如图
九,文中涉及到的各平台的版本查看:
[root@localhost luacache]# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core)
[root@localhost luacache]# /usr/local/openresty/bin/openresty -V nginx version: openresty/1.15.8.2 built by gcc 8.2.1 20180905 (Red Hat 8.2.1-3) (GCC) built with OpenSSL 1.1.0k 28 May 2019 TLS SNI support enabled
[root@localhost luacache]# /usr/local/soft/redis5/bin/redis-server --version Redis server v=5.0.7 sha=00000000:0 malloc=libc bits=64 build=8e31d2ed9a4c9593