1.生產消費者模型
消息對列
在生活中,其實有很多的例子,都類似消息隊列。
比如:工廠生產出來的面包,交給超市,商場來出售,客戶通過超市,商場來買面包,客戶不會針對某一個工廠去選擇,只管從超市買出來,工廠也不會管是哪一個客戶買了面包,只管生產出來之后,交給超市,商場來處理。
消息隊列(Message Queue)是一種應用間的通信方式,消息發送后可以立即返回,有消息系統來確保信息的可靠專遞,消息生產者只管把消息發布到MQ中而不管誰來取,消息消費者只管從MQ中取消息而不管誰發布的,這樣發布者和使用者都不用知道對方的存在。
使用消息隊列
首先,我們可以知道,消息隊列是一種異步的工作機制,比如說日志收集系統,為了避免數據在傳輸過程中丟失,還有訂單系統,下單后,會生成對應的單據,庫存的扣減,消費信息的發送,一個下單,產生這么多的消息,都是通過一個操作的觸發,然后將其他的消息放入消息隊列中,依次產生。再就是很多網站的,秒殺活動之類的,前多少名用戶會便宜,都是通過消息隊列來實現的。
這些例子,都是通過消息隊列,來實現,業務的解耦,最終數據的一致性,廣播,錯峰流控等等,從而完成業務的邏輯。
消息隊列產品
1)rabbit-MQ(最初起源於金融系統,用於分布式系統中存儲轉發消息。OpenStack)
2)Zero-MQ(SaltStack)
3)Kafka(JAVA)
4)redis(key:value數據庫,緩存,消息隊列)
2.Redis發布消息的兩種模式
任務隊列:顧名思義,就是“傳遞消息的隊列”。與任務隊列進行交互的實體有兩類,一類是生產者(producer),另一類則是消費者(consumer)。生產者將需要處理的任務放入任務隊列中,而消費者則不斷地從任務獨立中讀入任務信息並執行。
任務隊列的好處
1)松耦合。
生產者和消費者只需按照約定的任務描述格式,進行編寫代碼。
2)易於擴展。
多消費者模式下,消費者可以分布在多個不同的服務器中,由此降低單台服務器的負載。
發布-訂閱模式(publish-subscribe)
其實從Pub/Sub的機制來看,它更像是一個廣播系統,多個訂閱者(Subscriber)可以訂閱多個頻道(Channel),多個發布者(Publisher)可以往多個頻道(Channel)中發布消息
可以這么簡單的理解:
1)Subscriber:收音機,可以收到多個頻道,並以隊列方式顯示
2)Publisher:電台,可以往不同的FM頻道中發消息
3)Channel:不同頻率的FM頻道
一個發布者多個訂閱者模型
主要應用:通知、公告
多個發布者一個訂閱者模型
可以將PubSub做成獨立的HTTP接口,各應用程序作為Publisher向Channel中發送消息,Subscriber端收到消息后執行相應的業務邏輯,比如寫數據庫,顯示等等。
主要應用:排行榜、投票、計數。
多個發布者多個訂閱者模型
故名思議,就是可以向不同的Channel中發送消息,由不同的Subscriber接收。
主要應用:群聊、聊天。
Redis發布訂閱實踐
1)PUBLISH channel msg
將信息 message 發送到指定的頻道 channel
2)SUBSCRIBE channel [channel ...]
訂閱頻道,可以同時訂閱多個頻道
3)UNSUBSCRIBE [channel ...]
取消訂閱指定的頻道, 如果不指定頻道,則會取消訂閱所有頻道
4)PSUBSCRIBE pattern [pattern ...]
訂閱一個或多個符合給定模式的頻道,每個模式以 * 作為匹配符,比如 it* 匹配所 有以 it 開頭的頻道( it.news 、 it.blog 、 it.tweets 等等), news.* 匹配所有 以 news. 開頭的頻道( news.it 、 news.global.today 等等),諸如此類
5)PUNSUBSCRIBE [pattern [pattern ...]]
退訂指定的規則, 如果沒有參數則會退訂所有規則
6)PUBSUB subcommand [argument [argument ...]]
查看訂閱與發布系統狀態
_注意:_使用發布訂閱模式實現的消息隊列,當有客戶端訂閱channel后只能收到后續發布到該頻道的消息,之前發送的不會緩存,必須Provider和Consumer同時在線。
訂閱單個頻道
#第一個窗口
#登錄Redis
[root@db01 ~]# redis-cli -a 123
#在訂閱者的服務器上輸入訂閱zls
127.0.0.1:6379> SUBSCRIBE zls
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "zls"
3) (integer) 1
#第二個窗口
#登錄Redis
[root@db01 ~]# redis-cli -a 123
#在發布者的服務器上輸入信息
127.0.0.1:6379> PUBLISH zls "The Nice Boy Like Me."
(integer) 1
#第一個窗口
#在訂閱者的服務器上會看到如下信息
1) "message"
2) "zls"
3) "The Nice Boy Like Me."
訂閱多個頻道
#第一個窗口
#登錄Redis
[root@db01 ~]# redis-cli -a 123
#在訂閱者服務器上輸入訂閱所有頻道
127.0.0.1:6379> PSUBSCRIBE *
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "*"
3) (integer) 1
#第二個窗口
#在發布者服務器上輸入多頻道信息
127.0.0.1:6379> PUBLISH zls "The Nice Boy Like Me."
(integer) 1
127.0.0.1:6379> PUBLISH bgx "The Ugly Old Man Like Me."
(integer) 1
#第一個窗口
#在訂閱者的服務器上會看到如下信息
1) "pmessage"
2) "*"
3) "zls"
4) "The Nice Boy Like Me."
1) "pmessage"
2) "*"
3) "bgx"
4) "The Ugly Old Man Like Me."
消息隊列系統對比
客戶端在執行訂閱命令之后進入了訂閱狀態,只能接收 SUBSCRIBE 、PSUBSCRIBE、 UNSUBSCRIBE 、PUNSUBSCRIBE 四個命令。 開啟的訂閱客戶端,無法收到該頻道之前的消息,因為 Redis 不會對發布的消息進行持久化。 和很多專業的消息隊列系統(例如Kafka、RocketMQ、RabbitMQ)相比,Redis的發布訂閱略顯粗糙。
例如:無法實現消息堆積和回溯。但勝在足夠簡單,如果當前場景可以容忍的這些缺點,也不失為一個不錯的選擇。