redis 接口的二次封装(简化建连、拆连等细节)

先看一下官方的调用示例代码:

local redis = require("resty.redis")
local red = redis:new()

red:set_timeout(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

ok, err = red:set("dog", "an animal")
if not ok then
    ngx.say("failed to set dog: ", err)
    return
end

ngx.say("set result: ", ok)

-- put it into the connection pool of size 100,
-- with 10 seconds max idle time
local ok, err = red:set_keepalive(10000, 100)
if not ok then
    ngx.say("failed to set keepalive: ", err)
    return
end

这是一个标准的 Redis 接口调用,如果你的代码中 Redis 被调用频率不高,那么这段代码不会有任何问题。

但如果你的项目重度依赖 Redis,工程中有大量的程序在重复 创建连接-->数据操作-->关闭连接(或放到连接池) 这条完整的链路。甚至在调用完毕还要考虑不同的 return 情况做不同处理,你很快就会发现代码有大量的重复。

Lua 是不支持面向对象的。很多人用尽各种招数使用元表来模拟。可是,Lua 的发明者似乎不想看到这样的情形,因为他们把取长度的 __len 方法以及析构函数 __gc 留给了 C API,纯 Lua 只能望洋兴叹。

我们期望的代码应该是这样的:

期望它自身具备以下几个特征:

  • newconnect 函数合体,使用时只负责申请,尽量少关心什么时候具体连接、释放;

  • 默认 Redis 数据库连接地址,但是允许自定义;

  • 每次 Redis 使用完毕,自动释放 Redis 连接到连接池供其他请求复用;

  • 要支持 Redis 的重要优化手段 pipeline;

不卖关子,只要干货,我们最后是这样干的,可以这里看到 gist代码

调用示例代码:

在最终的示例代码中看到,所有的连接创建、连接销毁、以及连接池部分,都被完美隐藏了,我们只需要业关注务就可以了。妈妈再也不用担心我把 Redis 搞垮了。

Last updated