Redis 實現安全隊列


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM