当前位置: 首页 > 工具软件 > Nginx-Redis > 使用案例 >

Nginx Lua 开发 - Redis 操作

萧晔
2023-12-01

一、Nginx 支持3种方法访问 Redis

1)HttpRedis : 提供指令少,功能单一

2)HttpRedis2Module : 比 HttpRedis 操作更灵活,功能更强大

3)Lua-resty-redis 库 : Openresty 提供的操作 Redis 的接口库,需要通过 --with-luajit 编译安装

二、HttpRedis2Module 适合简单访问 Redis 数据

1)官方文档:https://www.nginx.com/resources/wiki/modules/redis2/

2)该模块需要编译安装:https://github.com/openresty/redis2-nginx-module/issues/23

3)使用:

在 nginx.conf 中配置

location /http2redisget {
    set_unescape_uri $key $arg_key;              # 通过get参数的key设置$key的值
    redis2_query get $key;                       # 获取key的值在redis中
    redis2_pass 127.0.0.1:6379;
}

location /http2redisset {
    set_unescape_uri $key $arg_key;
    set_unescape_uri $val $arg_val;
    redis2_query set $key $val;
    redis2_pass 127.0.0.1:6379;
}
curl "http://localhost:9999/http2redisset?key=hello&val=123"
> +OK

curl "http://localhost:9999/http2redisget?key=hello"        
> $3                                                       # $3 表示响应的数据长度
> 123

三、Lua-resty-redis 适合复杂应用

1)基本使用格式

location /luarestyredis {
    content_by_lua_block {
        -- 引入redis
        local redis = require "resty.redis"
        local red = redis:new()

        -- 设置超时时间为1秒
        red:set_timeout(1000)

        -- 连接redis
        local ok, err = red:connect("127.0.0.1", 6379)
        if not ok then
            ngx.say("fail to connect", err)
        end

        -- 设置key
        ok, err = red:set("dog", "an animal")
        if not ok then
            ngx.say("fail to set dog", err)
        else
            ngx.say("set result", ok)
        end

        -- 读取key
        local res, err = red:get("dog")
        if not res then
            ngx.say("fail to get dog", err)
            return
        end

        if res == ngx.null then
            ngx.say("dog not found")
            return 
        else
            ngx.say("dog :", res)
        end

        -- 关闭redis
        local ok, err = red:close()
        if not ok then
            ngx.say("fail to close : ", err)
            return
        end
    }
}

2)json返回

# 响应格式为json
location /luarestyredis_json {
    default_type application/json;
    content_by_lua '
        local key = ngx.req.get_uri_args()["key"]
        local redis = require "resty.redis"
        local cjson = require "cjson"

        local red = redis:new()

        local ok, err = red:connect("127.0.0.1", 6379)
        if not ok then
            ngx.exit(500)
        end

        local res, err = red:get(key)
        if res then 
            ngx.print(cjson.encode(res))
        end
    ';
}
curl "http://localhost:9999/http2redisget_json?key=hello" 
> "123"

3)需要注意:

a、使用本库不能用在 init_by_lua 、set_by_lua 、log_by_lua 、header_filter_by_lua 上下文中

b、resty.redis 不能存放在模块级的变量中(其他例程会分享),只能存放在局部变量或ngx.ctxtable中

c、如果使用 Nginx + ngx_lua 环境,需要单独引入模块

d、连接池 (set_keepalive):连接池是以工作线程为单位,若系统处理 1000 个请求,工作进程只有 10 个,则每个连接池容量应该是 1000/10 = 100 个,若配置成 1000,会浪费内存。

 类似资料: