Openresty连接redis

724次阅读
没有评论

共计 6310 个字符,预计需要花费 16 分钟才能阅读完成。

Openresty连接redis

职业中学习,断断续续,很久之前就知道openresty可以连接redis/mysql/pgsql等,今日开始看看openresty的lua-resty-redis模块,之前一直操作的是进程内的shared,一旦重启便会丢失数据,所以有一个外部内存服务是最好的。此处博主记录下opnresty连接redis的使用方式

lua-resty-redis

文档地址:https://github.com/openresty/lua-resty-redis

redis服务读者自行准备~

new方法创建object

syntax: red, err = redis:new()

Creates a redis object. In case of failures, returns nil and a string describing the error.

创建redis连接

syntax: ok, err = red:connect(host, port, options_table?)
syntax: ok, err = red:connect("unix:/path/to/unix.sock", options_table?)

如果要使用域名建立连接,则需要配置reslover

server {
    listen 80;
    reslover 114.114.114.114;
    location /test {
        content_by_lua_block {
        local redis = require "resty.redis"
        local red = redis:new()
        -- or connect via hostname, need to specify resolver just like above
        local ok, err = red:connect("redis-1.xadocker.cn", 6379)
        --- 略
        }
    }
}

无密码的redis连接

        local redis = require "resty.redis"
        local red = redis:new()
        red:set_timeout(1000,1000,1000) -- 1 sec
        local ok,err = red:connect("127.0.0.1",6379)

        ngx.log(ngx.INFO, " ok: ", ok, " err: ", err)
        if not ok then
            ngx.say("failed to connect: ",err)
            return
        end

有密码的redis连接

connect方法建立连接后,使用auth方法发起认证。类似redis-cli使用,先建链,后用auth指令。。。

        local redis = require "resty.redis"
        local red = redis:new()
        red:set_timeout(1000,1000,1000) -- 1 sec
        local ok,err = red:connect("127.0.0.1",6379)
        ngx.log(ngx.INFO, " ok: ", ok, " err: ", err)
        if not ok then
            ngx.say("failed to connect: ",err)
            return
        end
        local res,err = red:auth("xadpaas")
        ngx.log(ngx.INFO, " res: ", res, " err: ", err)
        if not res then
            ngx.say("failed to auth: ",err)
            return
        end

set和get相关方法

基本set方法

        local ok,err = red:set("name", "xadocker")
        if not ok then
            ngx.say("failed to set name: ", err)
            return
        end
        ngx.say("set result: ", ok)

基本get方法

        local res,err = red:get("name")
        if not res then
            ngx.say("failed to get name: ", res)
            return
        end
        ngx.say("get name: ", res)

若是keys不存在,返回的res是个userdata类型,其为null,而不是nil

2021/08/14 16:45:30 [info] 8606#0: *1 [lua] content_by_lua(redis.conf:32):19:  res: null type(res): userdata err: nil, client: 127.0.0.1, server: , request: "GET /test HTTP/1.1", host: "127.0.0.1:8085"

所以需要判断下是否为null

        local res, err = red:get("name")
        ngx.log(ngx.INFO, " res: ", res, " type(res): ", type(res)," err: ", err)
        if not res then
            ngx.say("failed to get name: ", err)
            return
        end
        if res == ngx.null then
            ngx.say("name not found.")
            return
        end
        ngx.say("get name: ", res)

mset方法和mget方法

    location /mset {
        content_by_lua_block {
            local redis = require "resty.redis"
            local red = redis:new()
            red:set_timeout(1000,1000,1000) -- 1 sec
            local ok,err = red:connect("127.0.0.1",6379)
            if not ok then
                ngx.say("failed to connect: ",err)
                return
            end
            local res, err = red:mset("name","xxxx","age",25)
            if not res then
                ngx.say("failed to mset: ", err)
                return
            end
            ngx.say("mset status: ", res)
        }
    }
    location /mget {
        content_by_lua_block {
            local redis = require "resty.redis"
            local red = redis:new()
            red:set_timeout(1000,1000,1000) -- 1 sec
            local ok,err = red:connect("127.0.0.1",6379)
            if not ok then
                ngx.say("failed to connect: ",err)
                return
            end
            local res, err = red:mget("name","age")
            if not res then
                ngx.say("failed to mget: ", err)
                return
            end
            ngx.say("mget status: ", res)
        }
    }

init_pipeline

使用pipeline合并提交操减少请求,从而减少rrt

        ngx.say("init_pipeline test")
        red:init_pipeline()
        red:set("age", 34)
        red:set("pet", "alsk")
        red:get("age")
        red:get("pet")
        local results, err = red:commit_pipeline()
        if not results then
            ngx.say("filed to commit the pipelined requests: ", err)
            return
        end
        for i,res in ipairs(results) do
            if type(res) == "table" then
                if res[1] == false then
                    ngx.say("failed to run command ", i, ": ", res[2])
                else
                    ngx.say("process the table value")
                end
             else
                 ngx.say(res)
             end
        end

获得如下输出

[root@nginx-cluster conf.d]# curl 127.0.0.1:8085/test
set result: OK
get name: xadocker
init_pipeline test
xadocker
null
OK
OK
34
alsk

注意:合并提交操作内的指令不要太多,避免造成io阻塞,可以用redis自带的压测命令测试下

[root@nginx-cluster conf.d]# redis-benchmark -t set -q
SET: 57045.07 requests per second

[root@nginx-cluster conf.d]# redis-benchmark -t set -q -P 2
SET: 117647.05 requests per second

[root@nginx-cluster conf.d]# redis-benchmark -t set -q -P 10
SET: 549450.56 requests per second

[root@nginx-cluster conf.d]# redis-benchmark -t set -q -P 30
SET: 769230.81 requests per second

[root@nginx-cluster conf.d]# redis-benchmark -t set -q -P 100
SET: 917431.19 requests per second

[root@nginx-cluster conf.d]# redis-benchmark -t set -q -P 200
SET: 900900.88 requests per second

用openresty模拟测试下

    location /singleSet {
        content_by_lua_block {
            local redis = require "resty.redis"
            local red = redis:new()
            red:set_timeout(1000,1000,1000) -- 1 sec
            local ok,err = red:connect("127.0.0.1",6379)
            if not ok then
                ngx.say("failed to connect: ",err)
                return
            end

            ngx.say("singleSet test start===")
            local stime = ngx.time()
            for i=1,100000 do
                local res,err = red:set("name"..i, "xadockerrrrrrrrrrrrrrrrrrrr")
                if not res then
                   ngx.say("failed to set ".."name"..i)
                   return
                end
            end
            ngx.say("singleSet test complete in: "..ngx.time()-stime)
        }
    }
    location /singleGet {
        content_by_lua_block {
            local redis = require "resty.redis"
            local red = redis:new()
            red:set_timeout(1000,1000,1000) -- 1 sec
            local ok,err = red:connect("127.0.0.1",6379)
            if not ok then
                ngx.say("failed to connect: ",err)
                return
            end
            ngx.say("singleGet test start===")
            local stime = ngx.time()
            for i=1,100000 do
                local res,err = red:get("name"..i)
                if not res then
                   ngx.say("failed to get ".."name"..i)
                   return
                end
            end
            ngx.say("singleGet test complete in: "..ngx.time()-stime.."s")
        }
    }
    location /pipelineSet {
        content_by_lua_block {
            local redis = require "resty.redis"
            local red = redis:new()
            red:set_timeout(1000,1000,1000) -- 1 sec
            local ok,err = red:connect("127.0.0.1",6379)
            if not ok then
                ngx.say("failed to connect: ",err)
                return
            end
            ngx.say("pipelineSet test start===")
            local stime = ngx.time()
            for i=1,1000 do
                red:init_pipeline()
                for j=1,100 do
                    red:set("name"..i..j, "xadxadxadxadxad"..i..j)
                end
                local results, err = red:commit_pipeline()
                if not results then
                    ngx.say("failed to commit the pipelined requests: ", err)
                    return
                end
            end
            ngx.say("pipelineSet test complete in: "..ngx.time()-stime.."s")
        }
    }
    location /pipelineGet {
        content_by_lua_block {
            local redis = require "resty.redis"
            local red = redis:new()
            red:set_timeout(1000,1000,1000) -- 1 sec
            local ok,err = red:connect("127.0.0.1",6379)
            if not ok then
                ngx.say("failed to connect: ",err)
                return
            end
            ngx.say("pipelineGet test start===")
            local stime = ngx.time()
            for i=1,1000 do
                red:init_pipeline()
                for j=1,100 do
                    red:get("name"..i..j)
                end
                local results, err = red:commit_pipeline()
                if not results then
                    ngx.say("failed to commit the pipelined requests: ", err)
                    return
                end
            end
            ngx.say("pipelineGet test complete in: "..ngx.time()-stime.."s")
        }
    }

获得的输出

[root@nginx-cluster conf.d]# curl 127.0.0.1:8085/singleSet
singleSet test start===
singleSet test complete in: 164s

[root@nginx-cluster conf.d]# curl 127.0.0.1:8085/singleGet
singleGet test start===
singleGet test complete in: 115s

[root@nginx-cluster conf.d]# curl 127.0.0.1:8085/pipelineSet
pipelineSet test start===
pipelineSet test complete in: 2s

[root@nginx-cluster conf.d]# curl 127.0.0.1:8085/pipelineGet
pipelineGet test start===
pipelineGet test complete in: 1s

# 似乎远远比不上redis-benmark的结果。。。。但至少两个测试都说明用pipeline的方式更高效

正文完
 
xadocker
版权声明:本站原创文章,由 xadocker 2021-08-14发表,共计6310字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)