Redis實現消息隊列的4種方案


原文鏈接:Redis實現消息隊列的方案

Redis作為內存中的數據結構存儲,常用作數據庫、緩存和消息代理。它支持數據結構,如 字符串,散列,列表,集合,帶有范圍查詢的排序集(sorted sets),位圖(bitmaps),超級日志(hyperloglogs),具有半徑查詢和流的地理空間索引。Redis具有內置復制,Lua腳本,LRU驅逐,事務和不同級別的磁盤持久性,並通過Redis SentinelRedis Cluster自動分區。

為了實現其出色的性能,Redis使用內存數據集(in-memory dataset)

MQ應用有很多,比如ActiveMQ,RabbitMQ,Kafka等,但是也可以基於redis來實現,可以降低系統的維護成本和實現復雜度,本篇介紹redis中實現消息隊列的幾種方案。

  • 基於List的 LPUSH+BRPOP 的實現
  • PUB/SUB,訂閱/發布模式
  • 基於Sorted-Set的實現
  • 基於Stream類型的實現

基於異步消息隊列List lpush-brpop(rpush-blpop)

使用rpushlpush操作入隊列,lpoprpop操作出隊列。

List支持多個生產者和消費者並發進出消息,每個消費者拿到都是不同的列表元素。

但是當隊列為空時,lpop和rpop會一直空輪訓,消耗資源;所以引入阻塞讀blpop和brpop(b代表blocking),阻塞讀在隊列沒有數據的時候進入休眠狀態

一旦數據到來則立刻醒過來,消息延遲幾乎為零。

注意

你以為上面的方案很完美?還有個問題需要解決:空閑連接的問題。

如果線程一直阻塞在那里,Redis客戶端的連接就成了閑置連接,閑置過久,服務器一般會主動斷開連接,減少閑置資源占用,這個時候blpop和brpop或拋出異常

所以在編寫客戶端消費者的時候要小心,如果捕獲到異常,還有重試。

缺點:

  • 消費者確認ACK麻煩,不能保證消費者消費消息后是否成功處理的問題(宕機或處理異常等),通常需要維護一個Pending列表,保證消息處理確認。
  • 不能做廣播模式,如pub/sub,消息發布/訂閱模型
  • 不能重復消費,一旦消費就會被刪除
  • 不支持分組消費

如何實現:Redis應用-異步消息隊列與延時隊列

PUB/SUB,訂閱/發布模式

SUBSCRIBE,用於訂閱信道

PUBLISH,向信道發送消息

UNSUBSCRIBE,取消訂閱

此模式允許生產者只生產一次消息,由中間件負責將消息復制到多個消息隊列,每個消息隊列由對應的消費組消費。

優點

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

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

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

缺點

消息一旦發布,不能接收。換句話就是發布時若客戶端不在線,則消息丟失,不能尋回

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

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

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

基於Sorted-Set的實現

Sortes Set(有序列表),類似於java的SortedSet和HashMap的結合體,一方面她是一個set,保證內部value的唯一性,另一方面它可以給每個value賦予一個score,代表這個value的

排序權重。內部實現是“跳躍表”。

有序集合的方案是在自己確定消息順ID時比較常用,使用集合成員的Score來作為消息ID,保證順序,還可以保證消息ID的單調遞增。通常可以使用時間戳+序號的方案。確保了消息ID的單調遞增,利用SortedSet的依據

Score排序的特征,就可以制作一個有序的消息隊列了。

優點

就是可以自定義消息ID,在消息ID有意義時,比較重要。

缺點

缺點也明顯,不允許重復消息(因為是集合),同時消息ID確定有錯誤會導致消息的順序出錯。

基於Stream類型的實現

 

 剩下的東西有待補充


免責聲明!

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



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