其實(shí)這一小節(jié)完全可以放到上一個(gè)小結(jié),只是這里用了完全不同的玩法,所以我還是決定單拿出來分享一下這個(gè)小細(xì)節(jié)。
上一小結(jié)有關(guān)訂閱部分的代碼,請看:
function _M.subscribe( self, channel )
local redis, err = redis_c:new()
if not redis then
return nil, err
end
local ok, err = self:connect_mod(redis)
if not ok or err then
return nil, err
end
local res, err = redis:subscribe(channel)
if not res then
return nil, err
end
res, err = redis:read_reply()
if not res then
return nil, err
end
redis:unsubscribe(channel)
self.set_keepalive_mod(redis)
return res, err
end
其實(shí)這里的實(shí)現(xiàn)是有問題的,各位看官,你能發(fā)現(xiàn)這段代碼的問題么?給個(gè)提示,在高并發(fā)訂閱場景下,極有可能存在漏掉部分訂閱信息。原因在與每次訂閱到內(nèi)容后,都會(huì)把 Redis 對象進(jìn)行釋放,處理完訂閱信息后再次去連接 Redis ,在這個(gè)時(shí)間差里面,很可能有消息已經(jīng)漏掉了。
正確的代碼應(yīng)該是這樣的:
function _M.subscribe( self, channel )
local redis, err = redis_c:new()
if not redis then
return nil, err
end
local ok, err = self:connect_mod(redis)
if not ok or err then
return nil, err
end
local res, err = redis:subscribe(channel)
if not res then
return nil, err
end
local function do_read_func ( do_read )
if do_read == nil or do_read == true then
res, err = redis:read_reply()
if not res then
return nil, err
end
return res
end
redis:unsubscribe(channel)
self.set_keepalive_mod(redis)
return
end
return do_read_func
end
調(diào)用示例代碼:
local red = redis:new({timeout=1000})
local func = red:subscribe( "channel" )
if not func then
return nil
end
while true do
local res, err = func()
if err then
func(false)
end
... ...
end
return cbfunc