1. 程式人生 > >Redis 實現安全佇列

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