Redis的列表數據結構可以讓我們方便的實現消息隊列
例如用 LPUSH(BLPUSH)把消息入隊,用 RPOP(BRPOP)獲取消息
絕大部分的情況下,這些操作都是沒問題的,但並不能保證絕對安全
當 LPOP 返回一個元素給客戶端的時候,會從 list 中把該元素移除,這意味着該元素就只存在於客戶端的上下文中,如果客戶端在處理這個返回元素的過程崩潰了,那么這個元素就永遠丟失了
如何解決?
redis 有一個 RPOPLPUSH (或者其阻塞版本的 BRPOPLPUSH)命令
命令格式
RPOPLPUSH source destination
原子性地返回並移除 source 列表的最后一個元素, 並把該元素放入 destination 列表的頭部
用這個命令可以保證隊列的安全問題:
使用 RPOPLPUSH 獲取消息時,RPOPLPUSH 會把消息返給客戶端,同時把該消息放入一個備份消息列表,並且這個過程是原子的,可以保證消息的安全,當客戶端成功的處理了消息后,就可以把此消息從備份列表中移除了
命令的阻塞與非阻塞區別
redis的命令中,很多都提供了阻塞與非阻塞兩個方式
例如 LPUSH 為非阻塞,BLPUSH 為阻塞方式
他們的區別是什么?
唯一的區別是當列表中沒有元素時,BRPOP命令會一直阻塞住連接,直到有新元素加入,而RPOP會直接返回nil
實際應用的區別
需要從隊列獲取任務
如果用非阻塞的方式,代碼會是這樣
# 無限循環讀取任務隊列中的內容
loop
$task = RPOR queue
if $task
# 如果有任務則執行
execute($task)
else
# 如果沒有就等待1秒
wait 1 second
當隊列中沒有任務時,每秒都會調用一次RPOP命令查看是否有新任務,可能會白白浪費很多系統資源,如果在有新任務加入隊列時就通知消費者就好了,這個需求就可以使用阻塞式命令來實現
loop
# 如果隊列中沒有任務,BRPOP命令會一直阻塞
# 0 表示一直等待,永不過期
$task = BRPOP queue, 0
# 有返回值就繼續執行
execute($task[1])
https://www.cnblogs.com/wangdaijun/p/6497403.html