頻道的訂閱與退訂
數(shù)據(jù)結(jié)構(gòu)
struct redisServer {
// ...
// 保存所有頻道的訂閱關(guān)系
dict *pubsub_channels;
// ...
};
示例:
image.png
訂閱:
def subscribe(*all_input_channels):
# 遍歷輸入的所有頻道
for channel in all_input_channels:
# 如果 channel 不存在于 pubsub_channels 字典(沒有任何訂閱者)
# 那么在字典中添加 channel 鍵栅组,并設(shè)置它的值為空鏈表
if channel not in server.pubsub_channels:
server.pubsub_channels[channel] = []
# 將訂閱者添加到頻道所對應(yīng)的鏈表的末尾
server.pubsub_channels[channel].append(client)
退訂:
def unsubscribe(*all_input_channels):
# 遍歷要退訂的所有頻道
for channel in all_input_channels:
# 在訂閱者鏈表中刪除退訂的客戶端
server.pubsub_channels[channel].remove(client)
# 如果頻道已經(jīng)沒有任何訂閱者了(訂閱者鏈表為空)
# 那么將頻道從字典中刪除
if len(server.pubsub_channels[channel]) == 0:
server.pubsub_channels.remove(channel)
模式的訂閱與退訂
數(shù)據(jù)結(jié)構(gòu):
struct redisServer {
// ...
// 保存所有模式訂閱關(guān)系
list*pubsub_patterns;
// ...
};
pubsubPattern:
typedef struct pubsubPattern {
// 訂閱模式的客戶端
redisClient *client;
robj *pattern;
// ...
}pubsubPattern ;
示例:
image.png
訂閱:
image.png
退訂:
image.png
發(fā)送消息:
發(fā)送消息到頻道:
image.png
發(fā)送消息到模式:
image.png
查看訂閱信息:
PUBSUB CHANNELS
PUBSUB CHANNELS [pattern]
- 無參數(shù): 返回服務(wù)器當(dāng)前被訂閱的所有頻道弯院。
- 有參數(shù): 返回那些與pattern模式相匹配的頻道贞瞒。
偽碼:
image.png
PUBSUB NUMSUB
PUBSUB NUMSUB[channel-1 channel-2 ... channel-n]
返回頻道的訂閱者數(shù)量
偽碼:
image.png
PUBSUB NUMPAT
返回服務(wù)器當(dāng)前被訂閱模式的梳理。
偽碼:
image.png
重點(diǎn)
- 訂閱信息由服務(wù)器進(jìn)程維持的 redisServer.pubsub_channels 字典保存摆寄,字典的鍵為被訂閱的頻道失暴,字典的值為訂閱頻道的所有客戶端。
- 當(dāng)有新消息發(fā)送到頻道時(shí)微饥,程序遍歷頻道(鍵)所對應(yīng)的(值)所有客戶端逗扒,然后將消息發(fā)送到所有訂閱頻道的客戶端上。
- 訂閱模式的信息由服務(wù)器進(jìn)程維持的 redisServer.pubsub_patterns 鏈表保存畜号,鏈表的每個(gè)節(jié)點(diǎn)都保存著一個(gè) pubsubPattern 結(jié)構(gòu)缴阎,結(jié)構(gòu)中保存著被訂閱的模式,以及訂閱該模式的客戶端简软。程序通過遍歷鏈表來查找某個(gè)頻道是否和某個(gè)模式匹配蛮拔。
- 當(dāng)有新消息發(fā)送到頻道時(shí),除了訂閱頻道的客戶端會(huì)收到消息之外痹升,所有訂閱了匹配頻道的模式的客戶端建炫,也同樣會(huì)收到消息。
- 退訂頻道和退訂模式分別是訂閱頻道和訂閱模式的反操作疼蛾。