首頁  >  文章  >  資料庫  >  如何基於redis實作訊息佇列

如何基於redis實作訊息佇列

(*-*)浩
(*-*)浩原創
2019-11-26 10:29:313352瀏覽

如何基於redis實作訊息佇列

訊息佇列,Message Queue,常用於解決並發系統中的資源一致性問題,提升峰值的處理能力,同時保證訊息的順序性、可恢復性、必送達性,對應用進行解耦,或實現非同步通訊等。 (建議學習:Redis影片教學

市面上的MQ應用有很多(例如:Kafka,RabbitMQ,Disque),同時也可以基於Redis 來實現,比較典型的方案有:

基於List的LPUSH BRPOP 的實作

PUB/SUB,訂閱/發布模式

基於Sorted-Set的實作

基於Stream類型的實作

在訊息佇列使用中,有生產者producter和消費者consumer。生產者負責產生訊息,消費者負責使用處理訊息。

生產,指的是將訊息放入訊息佇列。

消費,指的是讀取並處理訊息。通常一個訊息再被消費後,就應該從訊息佇列中刪除。

如何基於redis實作訊息佇列

基於List的LPUSH BRPOP 的實作

典型的指令為:##

LPUSH,将消息队列
BRPOP,从队列中取出消息,阻塞模式

就是一個典型的基於FIFL佇列的解決方案。其中LPUSH是生產者會做的事,而BRPOP是消費者會做的事。

此模式有許多優點:

實作簡單

#Reids支援持久化訊息,表示訊息不會遺失,可以重複檢視(注意不是消費,只看不用,LRANGE類別的指示)。

可以保證順序,保證使用LPUSH指令,可以保證訊息的順序性

使用RPUSH,可以將訊息放在佇列的開頭,達到優先訊息的目的,可以實現簡易的訊息優先隊列。

同時也有些缺點:

做消費確認ACK比較麻煩,就是無法保證消費者在讀取之後,未處理後的宕機問題。導致訊息意外遺失。通常需要自行維護一個Pending列表,保證訊息的處理確認。

不能做廣播模式,例如典型的Pub/Discribe模式。

不能重複消費,一旦消費就會被刪除

不支援分組消費,需要自己在業務邏輯層解決

PUB/SUB,訂閱/發布模式

SUBSCRIBE,用于订阅信道
PUBLISH,向信道发送消息
UNSUBSCRIBE,取消订阅

生產者和消費者透過相同的一個頻道(Channel)進行互動。頻道其實也就是隊列。通常會有多位消費者。多個消費者訂閱同一個頻道,當生產者向頻道發布訊息時,該頻道會立即將訊息逐一發佈給每個消費者。可見,該頻道對於消費者來說是發散的頻道,每個消費者都可以得到相同的訊息。典型的對多的關係。

典型的優點是:

典型的廣播模式,一個訊息可以發佈到多個消費者

多頻道訂閱,消費者可以同時訂閱多個頻道,從而接收多類訊息

訊息即時發送,訊息不用等待消費者讀取,消費者會自動接收到頻道發布的訊息

也有些缺點:

訊息一旦發布,不能接收。換句話說是發佈時若客戶端不在線,則訊息遺失,不能尋回

不能保證每個消費者接收的時間是一致的

若消費者客戶端出現訊息積壓,到一定程度,會被強制斷開,導致訊息意外遺失。通常發生在訊息的生產遠大於消費速度時

可見,Pub/Sub 模式不適合做訊息存儲,訊息積壓類的業務,而是擅長處理廣播,即時通訊,即時回饋的業務。

基於SortedSet有序集合的實作

ZADD KEY score member,压入集合
ZRANGEBYSCORE,依据score获取成员

有序集合的方案是在自己決定訊息順ID時比較常用,使用集合成員的Score作為訊息ID,保證順序,還可以保證訊息ID的單調遞增。通常可以使用時間戳 序號的方案。確保了訊息ID的單調遞增,利用SortedSet的依據Score排序的特徵,就可以製作一個有序的訊息佇列了。

和上面的方案相比,優點就是可以自訂訊息ID,在訊息ID有意義時,比較重要。缺點也明顯,不允許重複訊息(以為是集合),同時訊息ID確定有錯誤會導致訊息的順序出錯。

所以,若不是需要自訂訊息ID,這個方案好像有點雞肋…

#基於Stream 類型的實作##這個Stream類型redis就是為了實現訊息隊列的。支援自動產生訊息ID,分組消費,ACK,訊息轉移,佇列監控等核心訊息佇列功能

更多Redis相關技術文章,請造訪

Redis入門教學

欄位學習!

以上是如何基於redis實作訊息佇列的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn