共计 6310 个字符,预计需要花费 16 分钟才能阅读完成。
职业中学习,断断续续,很久之前就知道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的方式更高效
正文完