特性

  • 使用连接池
  • 连接只需要一次认证

项目源码

https://github.com/helloJiu/o...

安装

opm install openresty/lua-resty-redis

代码 redis.lua

-- redis客户端 
local redis = require("resty/redis")
local config = {
    host = "127.0.0.1",
    port = 6379,
    password = "",
    db_index = 0,
    max_idle_time = 30000,
    database = 0,
    pool_size = 100,
    timeout = 5000,
}

local _M = {}

function _M.new()
    local instance = {
        host = config.host or "127.0.0.1",
        port = config.port or 6379,
        password = config.password or "",
        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
    }
    setmetatable(instance, {__index = _M})
    return instance
end

function _M:exec(func)
    local red = redis:new()
    -- 为后续操作设置超时(以毫秒为单位)保护,包括connect方法。
    red:set_timeout(self.timeout)

    -- 建立连接
    local ok, err = red:connect(self.host, self.port)
    if not ok or err ~= nil then
        ngx.log(ngx.ERR, "redis: ", "connect error, host: " .. self.host .. ", port: " .. self.port, err)
        return nil, err
    end

    if self.password ~= "" then
        -- 如果连接来自于连接池中,get_reused_times() 永远返回一个非零的值
        -- 只有新的连接才会进行授权
        local count = red:get_reused_times()
        if count == 0 then
            ok, err = red:auth(self.password)
            if not ok or err ~= nil then
                ngx.log(ngx.ERR, "redis: ", "auth error, host: " .. self.host .. ", port: " .. self.port, err)
                red:close()
                return nil, err
            end
        end
    end

    if self.database ~= 0 then
        red:select(self.database)
    end

    -- 执行业务逻辑
    local res, err = func(red)
    -- print(res, ', ', type(res), ', ', err, ', ', type(err))
    if res == nil or err ~= nil then
        -- 表示获取数据错误, 不讲连接放回连接池
        ngx.log(ngx.ERR, "redis: ", "exec command error" .. self.host .. ", port: " .. self.port, err)
        red:close()
        return nil, err
    end
    -- 将连接放回连接池
    red:set_keepalive(self.max_idle_time, self.pool_size)
    -- 转换结果
    if self:is_redis_null(res) then
        res = nil
    end

    return res, err
end

function _M:is_redis_null( res )
    if type(res) == "table" then
        for k,v in pairs(res) do
            if v ~= ngx.null then
                return false
            end
        end
        return true
    elseif res == ngx.null then
        return true
    elseif res == nil then
        return true
    end

    return false
end

return _M

实际使用

local redis = require("redis")
local red = redis.new()
local v, err = red:exec(function(red)
    return red:get("wechat:login_key")
end)

-- print(v, type(v), err, type(err))
if not v then
    -- 处理key不存在情况
end
-- 处理存在情况

参考文章


其实我很dou
4 声望2 粉丝

php