利用 Lua 的函数式编程简化 lua-resty-redis 的使用

在利用 OpenResty 编写高性能服务的时候,颇有可能会使用到 Redis。在 OpenResty 中,咱们一般使用 lua-resty-redis 这个模块操做 Redis。html

在 lua-resty-redis 的示例中,咱们能够总结出如下几个步骤:git

  • 导入 resty.redis 模块github

  • 实例化 redis 对象:redis

local red = redis:new()
red:set_timeout(1000)
  • 链接到服务器:编程

local ok, err = red:connect("127.0.0.1", 6379)
  • 操做 Redis服务器

  • 将链接添加到链接池中函数式编程

local ok, err = red:set_keepalive(1000, 100)

以上的几个步骤是标准的使用方式,咱们须要在每一个使用的地方重复上面的几个步骤。不知不觉,Lua 代码会变的庞大起来。函数

经过上面的步骤,咱们不难发现: 除了 Redis 操做不同,从实例化 Redis 到最后的链接资源管理都是同样的。这时候,咱们就能够使用通用的处理流去标准化它了!性能

OpenResty最佳实践 中有章节介绍了对 lua-resty-redis 的第二次简化封装跟须要注意的事项。可是,我仍是利用了 Lua 支持函数式编程的特性作了一个更加简化的版本:ui

local redis = require "resty/redis"

local log = ngx.log
local ERR = ngx.ERR
local setmetatable = setmetatable

local _M = {
    _VERSION = "1.0.0",
    _AUTHOR = "Andy Ai"
}

local mt = { __index = _M }

local function errlog(...)
    log(ERR, "Redis: ", ...)
end

function _M.exec(self, func)

    local red = redis:new()
    red:set_timeout(self.timeout)

    local ok, err = red:connect(self.host, self.port)
    if not ok then
        errlog("Cannot connect, host: " .. self.host .. ", port: " .. self.port)
        return nil, err
    end

    red:select(self.database)

    local res, err = func(red)
    if res then
        local ok, err = red:set_keepalive(self.max_idle_time, self.pool_size)
        if not ok then
            red:close()
        end
    end
    return res, err
end

function _M.new(opts)
    local config = opts or {}
    local self = {
        host = config.host or "127.0.0.1",
        port = config.port or 6379,
        timeout = config.timeout or 5000,
        database = config.database or 0,
        max_idle_time = config.max_idle_time or 60000,
        pool_size = config.pool_size or 100
    }
    return setmetatable(self, mt)
end

return _M

从上面的代码中能够看出:

咱们将 Redis 的操做当作一个函数,在这个函数执行以前进行实例化跟链接;在函数执行以后进行链接资源的管理。

而,在实际的使用过程当中也变得很是简单:

local redis = require("resty.rediscli")

local red = redis.new({host = "127.0.0.1"})
local res, err = red:exec(
    function(red)
        return red:get("123456")
    end
)

使用 Redis 的 Pipeline 也一样很简单:

red:exec(
    function(red)
        red:init_pipeline()
        red:set(key, value)
        red:expire(key, expires)
        return red:commit_pipeline()
    end
)

怎么样? 咱们使用 Lua 支持函数编程的特性恰到好处地将代码很好地简化了。这样,无论是咱们在实现逻辑,仍是在维护逻辑均可以把精力更多地放在业务实现上,而不是处理这些琐碎资源管理。

上面的代码能够在 GitHub 上获取: lua-resty-utils。另外,不须要担忧它的稳定性!它已经被使用在 GrowingIO 的几个很是重要的服务上!

相关文章
相关标签/搜索