一、發布與訂閱概述
Redis提供了基于“發布/訂閱”模式的消息機制,此種模式下,消息發布者和訂閱者不進行直接通信,發布者客戶端向指定的頻道(channel)發布消息,訂閱該頻道的每個客戶端都可以收到該消息。
?下圖展示了頻道 channel1 , 以及訂閱這個頻道的三個客戶端 —— client2 、 client5 和 client1 之間的關系:
當有新消息通過 PUBLISH 命令發送給頻道 channel1 時, 這個消息就會被發送給訂閱它的三個客戶端:
Redis主要提供了發布消息、訂閱頻道、取消訂閱以及按照模式訂閱和取消訂閱等命令
二、發布消息(publish)
PUBLISH <channel> <message>
當一個客戶端執行PUBLISH命令的時候,會將消息message發送給頻道channel
例如:下面操作會向channel:sports頻道發布一條消息“Tim won the championship”,返回結果為訂閱者個數,因為此時沒有訂閱,所以返回結果為0
publish channel:sports "Tim won the championship"
二、訂閱消息(subscribe)
subscribe channel [channel...]
訂閱者可以訂閱一個或多個頻道
注意事項:
客戶端在執行訂閱命令之后進入了訂閱狀態,只能接收subscribe、 psubscribe、unsubscribe、punsubscribe的四個命令
新開啟的訂閱客戶端,無法收到該頻道之前的消息,因為Redis不會對發布的消息進行持久化
演示案例
下面操作為當前客戶端訂閱了channel:sports頻道:
subscribe channel:sports
?
此時右側另一個客戶端向channel:sports頻道發布一條消息,右側客戶端會收到這條消息
publish channel:sports "James lost the championship"
開發提示:和很多專業的消息隊列系統(例如Kafka、RocketMQ)相比,Redis的發布訂閱略顯粗糙,例如無法實現消息堆積和回溯。但勝在足夠簡單,如果當前場景可以容忍的這些缺點,也不失為一個不錯的選擇
三、取消訂閱(unsubscribe)
unsubscribe [channel [channel ...]]
客戶端可以通過unsubscribe命令取消對指定頻道的訂閱,取消成功后, 不會再收到該頻道的發布消息
取消訂閱只對本個客戶端有效,不會對其他客戶端造成影響
例如:
?
四、模式訂閱/取消模式訂閱(psubscribe、punsubscribe)
psubscribe pattern [pattern...]
punsubscribe [pattern [pattern ...]]
psubscribe和punsubscribe是支持glob風格的訂閱/取消訂閱,稱之為“模式訂閱”
例如:
下面左側客戶端訂閱以it開頭的所有頻道
psubscribe it*
?
右側客戶端向itformation頻道發送一條消息,左側客戶端可以收到這條消息
五、查詢訂閱
①查詢活躍的頻道
pubsub channels [pattern]
所謂活躍的頻道是指當前頻道至少有一個訂閱者,其中[pattern]是可以指定具體的模式
例如,下面左側客戶端訂閱一個名為“it_redis”的頻道,右側使用pubsub查詢,結果會顯示出來
當然,我們也可以具體指出查詢哪個頻道,如果頻道不存在會返回空
當有模式訂閱時,也可以檢測出來
②查看頻道訂閱數
pubsub numsub [channel ...]
該命令不僅可以檢測出是否有活躍的頻道,還能檢測出頻道的訂閱數
例如,左側一個客戶端訂閱channel:sports頻道,右側客戶端查詢結果為1
③查看模式訂閱數
pubsub numpat
該命令可以查詢出當前服務器中有多少個模式訂閱
例如,當前所有客戶端中只有左側一個訂閱,并且不是模式訂閱,所以右側結果顯示為0
現在我們在左側開啟模式訂閱,右側查詢結果顯示為1
六、發布-訂閱的使用場景
聊天室、公告牌、服務之間利用消息解耦都可以使用發布訂閱模式
下面以簡單的服務解耦進行說明。如下圖所示,圖中有兩套業務:
上面為視頻管理系統,負責管理視頻信息
下面為視頻服務面向客戶,用戶可以通過各種客戶端(手機、瀏覽器、接口)獲取到視頻信息
假如視頻管理員在視頻管理系統中對視頻信息進行了變更,希望及時通知給視頻服務端,就可以采用發布訂閱的模式,發布視頻信息變化的消息到指定頻道,視頻服務訂閱這個頻道及時更新視頻信息,通過這種方式可以有效解決兩個業務的耦合性
視頻服務訂閱video:changes頻道如下:
subscribe video:changes
視頻管理系統發布消息到video:changes頻道如下:
publish video:changes "video1,video3,video5"
當視頻服務收到消息,對視頻信息進行更新,如下所示:
for video in video1,video3,video5
update {video}