在利用 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 的幾個很是重要的服務上!