如何用Lua脚本基于OpenResty、Redis实现数据的缓存?

也许有人对于OpenResty不太熟悉,但是一说到Nginx,可能都有所了解。作为控制速率和并发量控制的Nginx被很多公司所采用,而OpenResty就是在Nginx的基础上升级的,提供了Lua扩展,大大提升了Nignx对并发的处理能力,可以达到10K~1000K。OpenResty其实和Tengine一样,都是基于Nginx的衍生版本,融入了各自一些业务的新特性。

这里用一个例子来说明使用Lua脚本,通过OpenResty和Redis实现业务数据的缓存。一般商城系统都会包括各种各样的广告,对于首页的广告访问量一般来说都是比较频繁的。如果每访问一次就去请求Mysql或者Oracle数据库,势必会给数据库带来一定的压力。所以经常的做法就是这部分不易经常变化的数据缓存下来。浏览器访问时直接访问缓存获取数据,如果没有再来请求数据库。

如上图所示,首页广告访问的思路分为以上几个步骤:

1)用户请求地址,访问OpenResty,从Nginx的本地缓存(Nginx-Cache)中获取,如果获取到直接返回,获取不到则进行下一步。

2)通过Lua脚本访问Redis中的数据,如果有则直接返回【且会先把数据放到Nginx的本地缓存中】,没有则直接进行下一步。

3)通过Lua脚本访问Mysql,从Mysql中获取数据,再将数据存到Redis中,并返回结果。

OpenResty的安装

这里只介绍一下Linux环境下OpenResty的安装。

① 分别执行以下命令进行安装

# 添加仓库执行命令
yum install yum-utils
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo

# 执行安装
yum install openresty

       ② 安装成功后,会在默认目录【/usr/local/openresty】有对应的内容。由于OpenResty是基于Nginx的衍生的,因此,在OpenResty下其实就已经安装好了Nginx【/usr/local/openresty/nginx目录】。我们还需要去修改nginx.conf将配置文件使用的根设置为root,这里设置的目的就是将来使用Lua脚本的时候,可以直接加在Root下的Lua脚本【这里根据自己的需要设置用户以及目录】。

另外由于会使用Nginx的缓存模块,所以在conf中也需要事先配置好Nginx缓存模块。

脚本编写

按照上述步骤,整个访问分为三个环节。具体代码以及详细解释如下:

ngx.header.content_type="application/json;charset=utf8"
-- 获取请求参数
local uri_args = ngx.req.get_uri_args();
-- 获取请求的ID
local id = uri_args["id"];
-- 获取本地缓存
local cache_ngx = ngx.shared.dis_cache;
-- 根据ID 获取本地缓存数据
local contentCache = cache_ngx:get('content_cache_'..id);
-- 判断从本地是否获取的有数据
if contentCache == "" or contentCache == nil then
    -- 本地没有,则去读取Redis
    -- 加在redis模块
    local redis = require("resty.redis");
    local red = redis:new()
    red:set_timeout(2000)
    -- 连接redis
    red:connect("192.168.132.132", 6379)
    -- 查询数据
    local rescontent=red:get("content_"..id);
    -- 判断从redis是否获取的有数据
    if ngx.null == rescontent then
        -- 没有,则直接从Mysql中获取数据
        local cjson = require("cjson");
        local mysql = require("resty.mysql");
        local db = mysql:new();
        db:set_timeout(2000)
        local props = {
            host = "192.168.132.132",
            port = 3306,
            database = "changgou_content",
            user = "root",
            password = "123456"
        }
        local res = db:connect(props);
        -- 执行SQL并将结果转换成json数据格式
        local select_sql = "select url,pic from tb_content where status ='1' and category_id="..id.." order by sort_order";
        res = db:query(select_sql);
        local responsejson = cjson.encode(res);
        -- 设置到Redis中
        red:set("content_"..id,responsejson);
        -- 返回结果
        ngx.say(responsejson);
        -- 关闭数据库
        db:close()
    else
        -- 设置到Nginx Cache中
        cache_ngx:set('content_cache_'..id, rescontent, 2*60);
        -- 返回结果
        ngx.say(rescontent)
    end
    -- 关闭Redis的连接
    red:close()
else
    -- 返回结果
    ngx.say(contentCache)
end

配置拦截路由

脚本写好之后,需要去配置相应的Server拦截对应的路径,拦截后,交给对应的Lua脚本进行处理。

server{
    
    listen 80;
    # 监听域名
    server_name localhost;
    
    # 表示所有以localhost/read_content的请求都由该配置处理
    localtion /read_content {
        # 都交给/usr/local/server/lua/read_content.lua脚本进行处理
        content_by_lua_file /usr/local/server/lua/read_content.lua;
    }
}

每次修改了Nginx.conf文件都需要去重新启动Nginx【/usr/local/openresty/nginx】。以上使用Lua脚本以及OpenResty、Redis的缓存就简单实现了。

猜你喜欢

转载自blog.csdn.net/qq_35363507/article/details/115520108