- 什么是發(fā)布訂閱
- Redis發(fā)布訂閱(pub/sub)是一種消息通訊模式,發(fā)送者(pub)發(fā)送消息,訂閱者(sub)接收消息。
- Redis客戶端可以通過廣播的方式將消息(message)同時(shí)發(fā)送給可能存在的多個(gè)客戶端,并且發(fā)送消息的客戶端不需要知道接受消息的客戶端的具體信息。(發(fā)布消息的客戶端和接收消息的客戶端兩者之間沒有直接聯(lián)系)
- 客戶端可以訂閱(subscribe)任意數(shù)量的頻道(channel),每當(dāng)有新消息被發(fā)送到訂閱的頻道時(shí),信息就會(huì)被發(fā)送給所有訂閱指定頻道的客戶端。
- 一個(gè)頻道可以被多個(gè)客戶端訂閱,一個(gè)客戶端也可以訂閱多個(gè)頻道。
- 使用場(chǎng)景
- 實(shí)時(shí)溝通消息系統(tǒng)
- 微信公眾號(hào)(點(diǎn)擊關(guān)注即訂閱該公眾號(hào),公眾號(hào)發(fā)布博文后,訂閱的用戶就可以監(jiān)聽到)
- 粉絲關(guān)注
- 文章推送
- 電商中,用戶下單成功后向指定頻道發(fā)送消息,下游業(yè)務(wù)訂閱支付結(jié)果處理后續(xù)業(yè)務(wù)。
-
圖解
三個(gè)客戶端分別訂閱channel1和channel2 2個(gè)頻道
image.png
發(fā)布者(publisher)向channel1頻道發(fā)送了的消息被channel1的訂閱者client1、client2、client3同時(shí)接收到,發(fā)布者向channel2發(fā)送的消息只能被channel2的訂閱者client2、client3接收到,client1無法接收
image.png 命令行實(shí)現(xiàn)
- 客戶端訂閱channel1頻道(客戶端1)
# 訂閱1個(gè)或者多個(gè)頻道subscribe channel [channel ... ]
subscribe channel1

image.png
- 給channel1頻道發(fā)送消息 hello(客戶端2)
publish channel hello
# 返回頻道訂閱者的數(shù)量

image.png
- 打開客戶端1可以看見發(fā)送的消息

image.png
- 退訂頻道
unsubscribe channel [channel ... ]
- 查看訂閱與發(fā)布系統(tǒng)的狀態(tài)
pubsub channels [argument [atgument ...] ]
- 為什么要使用發(fā)布和訂閱
- 消息發(fā)送訂閱功能很多大廠使用的是kafka、RabbitMQ、ActiveMQ、RocketMQ等消息隊(duì)列,redis的發(fā)布訂閱比較前者相對(duì)輕量,對(duì)于數(shù)據(jù)安全性要求不高的公司可以直接使用
- redis的List數(shù)據(jù)結(jié)構(gòu)提供了blpop、brpop命令結(jié)合rpush、lpush可以實(shí)現(xiàn)消息隊(duì)列機(jī)制,可以基于雙端鏈表實(shí)現(xiàn)消息的發(fā)布與訂閱(比較笨重,不如直接使用發(fā)布訂閱功能)
- 不支持一對(duì)多的消息發(fā)送
- 如果生產(chǎn)者的速度遠(yuǎn)遠(yuǎn)大于消費(fèi)者,容易堆積大量未消費(fèi)的信息
- 雙端隊(duì)列只能有一個(gè)或者多個(gè)消費(fèi)者輪著去消費(fèi),但是不能將消息同時(shí)發(fā)送給其他消費(fèi)者
- redis發(fā)布訂閱模式,生產(chǎn)者生產(chǎn)完消息直接通過頻道分發(fā)消息給訂閱了該頻道的所有消費(fèi)者
- 兩種實(shí)現(xiàn)模式
- 上述4為“基于頻道”的發(fā)布訂閱模式
- 基于模式配(pattern)的發(fā)布訂閱模式
- 訂閱一個(gè)或者多個(gè)符合給定模式的頻道,每個(gè)模式以作為匹配符;例如cn 匹配所有以cn開頭的頻道
psubscribe pattern1 [pattern...]
# 訂閱者訂閱頻道 訂閱a?和com.*兩種模式的頻道 ?表示一個(gè)占位符 a?表示匹配 aa、ab、ac等a開頭的兩個(gè)字符的頻道
psubscribe a? com.*
# 發(fā)布者發(fā)布消息
publish ahead "hello" ——————(integer 1) 發(fā)布失敗,沒有訂閱者
publish aa "hello"——————(integer 1) 有1個(gè)匹配著
publish com.cn "hello"——————(integer 1) 有1個(gè)匹配著
- 退訂所有指定模式的頻道,如果pattern未指定則訂閱的所有模式都被退訂
punsubscribe [pattern [pattern ...] ]
- 實(shí)現(xiàn)原理
- 基于頻道模式
- 由底層字典實(shí)現(xiàn),所有pubsub_channels是一個(gè)字典類型。字典的key為訂閱的頻道,value為一個(gè)鏈表,鏈表中保存了所有訂閱該頻道的客戶端

image.png
- 基于匹配模式
- 底層由pubsub_pattern節(jié)點(diǎn)的鏈表實(shí)現(xiàn)
- 新增一個(gè)pubsub_pattern數(shù)據(jù)結(jié)構(gòu)添加到鏈表的最后尾部,同時(shí)保存客戶端ID
-
取消訂閱模式:從當(dāng)前的鏈表pubsub_pattern結(jié)構(gòu)中刪除需要取消的pubsub_pattern結(jié)構(gòu)
image.png


