簡單介紹下Redis消息隊列,實際生產環境中,大數據高並發時,不建議使用Redis做消息隊列中間件


十年河東,十年河西,莫欺少年窮

學無止境,精益求精

首先說下,我的 Redis 系列博客如下:

[置頂] 高並發時,使用Redis應注意的問題【緩存穿透、緩存擊穿.、緩存雪崩】

windows環境下配置Redis主從復制-一主二仆,薪火相傳、反客為主、哨兵模式

Redis 持久化技術 ,大名鼎鼎的Rdb和Aof,你會選誰呢?

簡單介紹下Redis消息隊列,實際生產環境中,大數據高並發時,不建議使用Redis做消息隊列中間件

Redis 事務,和傳統的關系型數據庫ACID並不同,別搞混了

Redis常用配置redis.conf介紹,別把默認配置部署到到服務器,否則,會被領導罵的

C# Nuget程序集StackExchange.Redis操作Redis 及 Redis 視頻資源 及 相關入門指令 牛逼不,全都有

Redis 的基礎數據類型

Window環境下安裝Redis 並 自啟動Redis 及 Redis Desktop Manager

進入正文

Redis消息隊列的關鍵字

Pub/Sub(發布/訂閱)

PSUBSCRIBE

訂閱一個或多個符合給定模式的頻道。

每個模式以 * 作為匹配符,比如 it* 匹配所有以 it 開頭的頻道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有以 news. 開頭的頻道( news.it 、 news.global.today 等等),諸如此類。

PUBLISH

將信息 message 發送到指定的頻道 channel 。意思就是指:發布消息,訂閱者可以接收

PUBSUB

 是一個查看訂閱與發布系統狀態的內省命令, 它由數個不同格式的子命令組成, 以下將分別對這些子命令進行介紹。
PUNSUBSCRIBE

指示客戶端退訂所有給定模式。

如果沒有模式被指定,也即是,一個無參數的 PUNSUBSCRIBE 調用被執行,那么客戶端使用 PSUBSCRIBE 命令訂閱的所有模式都會被退訂。在這種情況下,命令會返回一個信息,告知客戶端所有被退訂的模式。

SUBSCRIBE

訂閱給定的一個或多個頻道的信息。
UNSUBSCRIBE

指示客戶端退訂給定的頻道。

如果沒有頻道被指定,也即是,一個無參數的 UNSUBSCRIBE 調用被執行,那么客戶端使用 SUBSCRIBE 命令訂閱的所有頻道都會被退訂。在這種情況下,命令會返回一個信息,告知客戶端所有被退訂的頻道。

命令示例

關注:

 SUBSCRIBE k1 k2 k3 k4 k5
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "k1"
3) (integer) 1
1) "subscribe"
2) "k2"
3) (integer) 2
1) "subscribe"
2) "k3"
3) (integer) 3
1) "subscribe"
2) "k4"
3) (integer) 4
1) "subscribe"
2) "k5"
3) (integer) 5

發布:

C:\Users\chenwolong>redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> PUBLISH k1 "hello My Name is k1"
(integer) 1
127.0.0.1:6379> PUBLISH k2 "hello My Name is k2"
(integer) 1
127.0.0.1:6379> PUBLISH k3 "hello My Name is k3"
(integer) 1

發布消息后,訂閱者界面就可以看到發布的消息

 

 關於更多的指令演示,在此不做了,有興趣的可以參考:Redis中文網

最后貼出一個Redis實現消息隊列的案例

基於Redis實現消息隊列典型方案

1 概述
2 基於List的 LPUSH+BRPOP 的實現
3 PUB/SUB,訂閱/發布模式
4 基於SortedSet有序集合的實現
5 基於 Stream 類型的實現
6 其他實現

1 概述

消息隊列,Message Queue,常用於解決並發系統中的資源一致性問題,提升峰值的處理能力,同時保證消息的順序性、可恢復性、必送達性,對應用進行解耦,或者實現異步通訊等。市面上的 MQ應用有很多(例如:Kafka,RabbitMQ,Disque),同時也可以基於 Redis 來實現,比較典型的方案有:

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

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

生產,指的是將消息放入消息隊列。 消費,指的是讀取並處理消息。通常一個消息再被消費后,就應該從消息隊列中刪除。

 

 

接下來分別討論具體實現方案。

2 基於List的 LPUSH+BRPOP 的實現

典型的命令為:

LPUSH,將消息隊列
BRPOP,從隊列中取出消息,阻塞模式

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

該模式有很多優點:

  • 實現簡單
  • Reids支持持久化消息,意味着消息不會丟失,可以重復查看(注意不是消費,只看不用,LRANGE類的指令)。
  • 可以保證順序,保證使用LPUSH命令,可以保證消息的順序性
  • 使用RPUSH,可以將消息放在隊列的開頭,達到優先消息的目的,可以實現簡易的消息優先隊列。

同時也有些劣勢:

  • 做消費確認ACK比較麻煩,就是不能保證消費者在讀取之后,未處理后的宕機問題。導致消息意外丟失。通常需要自己維護一個Pending列表,保證消息的處理確認。
  • 不能做廣播模式,例如典型的Pub/Discribe模式。
  • 不能重復消費,一旦消費就會被刪除
  • 不支持分組消費,需要自己在業務邏輯層解決
注意,沒有好不好的技術,只有適合不適合。

3 PUB/SUB,訂閱/發布模式

SUBSCRIBE,用於訂閱信道
PUBLISH,向信道發送消息
UNSUBSCRIBE,取消訂閱

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

典型的優點是:

  • 典型的廣播模式,一個消息可以發布到多個消費者
  • 多信道訂閱,消費者可以同時訂閱多個信道,從而接收多類消息
  • 消息即時發送,消息不用等待消費者讀取,消費者會自動接收到信道發布的消息

也有些缺點:

  • 消息一旦發布,不能接收。換句話就是發布時若客戶端不在線,則消息丟失,不能尋回
  • 不能保證每個消費者接收的時間是一致的
  • 若消費者客戶端出現消息積壓,到一定程度,會被強制斷開,導致消息意外丟失。通常發生在消息的生產遠大於消費速度時

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

4 基於SortedSet有序集合的實現

ZADD KEY score member,壓入集合
ZRANGEBYSCORE,依據score獲取成員

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

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

所以,若不是需要自定義消息ID,這個方案好像有點雞肋...

5 基於 Stream 類型的實現

這個Stream類型redis就是為了實現消息隊列的。支持自動生成消息ID,分組消費,ACK,消息轉移,隊列監控等核心消息隊列功能,請參考:基於Redis的Stream類型的完美消息隊列解決方案,http://www.hellokang.net/redis/stream.html,來獲取完整方案。

6 其他實現

很多成熟的MQ產品:

 @天才卧龍的博客


免責聲明!

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



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