概要
redis的每個server例項都維護著乙個儲存伺服器狀態的redisserver結構
struct redisserver
;pubsub_channels記錄了所有客戶端訂閱的頻道的資訊。資料型別是dict,dict中的key代表了channel,而val儲存了關注頻道的所有clients。
redis的發布訂閱模式
訂閱者通過sub命令訂閱頻道,server使用pub命令把訊息推送到符合條件的pubsub_channels中。
內部資料結構
pubsub_channels是乙個字典結構,字典內部使用hash表儲存和索引資料。
實現字典的可選資料結構
hash表:簡單但是不穩定的基於陣列的衝突解決法;簡單且平均效率穩定的鏈式位址的衝突解決法;
字典樹:使用樹結構。
redis採用hash的鏈式位址法作為實現,好處是直觀、簡單、可期待平均時間複雜度較小且平穩。
typedef struct dict dict;
dict使用兩個hash表進行索引,當進行rehash的時候使用ht[1]的hash表,其他時候都使用hd[0]的hash表。
使用的hash表的定義如下
typedef struct dictht dictht;
table是乙個儲存dictentry*指標的陣列,table中的每一項都是乙個指向dictentry結構的指標,同時每一項也都帶有乙個指向下一項的指標。可以看出這是乙個使用鏈位址法解決衝突的hash結構。
dictentry的定義,包含key、value、next。
/** 雜湊表節點
*/typedef struct dictentry v;
// 指向下個雜湊表節點,形成鍊錶
struct dictentry *next;
} dictentry;
客戶端訂閱頻道
就是字典中插入新元素的過程
// 關聯示意圖
// /* add the client to the channel -> list of clients hash table */
// 從 pubsub_channels 字典中取出儲存著所有訂閱了 channel 的客戶端的鍊錶
// 如果 channel 不存在於字典,那麼新增進去
de = dictfind(server.pubsub_channels,channel);
if (de == null) else
// before:
// 'channel' : [c1, c2]
// after:
// 'channel' : [c1, c2, c3]
// 將客戶端新增到鍊錶的末尾
listaddnodetail(clients,c);
1.查詢server是否包含指定頻道
2.如果頻道存在就獲取頻道指向的list位址;如果頻道不存在,就建立頻道和list
3.使用步驟2的list,將客戶端新增到list的末尾。
完成這三步以後,server維護的發布訂閱頻道就新增了乙個頻道和關注的客戶端,server發布時檢測發布訂閱字典,獲取訂閱客戶端並依次傳送。
server發布訊息到channel
/* send to clients listening for that channel */
// 取出包含所有訂閱頻道 channel 的客戶端的鍊錶
// 並將訊息傳送給它們
de = dictfind(server.pubsub_channels,channel);
if (de)
}結合訂閱者訂閱的過程,發布過程就是乙個查詢訂閱者並輪詢傳送訊息給訂閱者的過程。
Redis發布訂閱模式
publish subscribe 發布訂閱模式的原理 包含兩個角色,乙個是發布者,乙個是訂閱者 訂閱者可以訂閱乙個或者多個頻道channel 發布者可以向指定頻道發布資訊 通過publish發布訊息 publish channel message publish channel1.1 maizie...
redis訂閱發布模式
理論遲點再補,先上 直接上 demopub.php 發布者 redis new redis redis connect localhost 6379 redis publish mcs 麒麟之才 demosub.php 訂閱者 redis new redis redis connect 127.0....
redis發布訂閱模式
發布 訂閱 模式包含兩種角色,分別是發布者和訂閱者。訂閱者可以訂閱乙個或者多個頻道 channel 而發布者可以向指定的頻道 channel 傳送訊息,所有訂閱此頻道的訂閱者都會收到此訊息。此模式允許生產者只生產一次訊息,由中介軟體負責將訊息複製到多個訊息佇列,每個訊息佇列由對應的消費組消費。模糊匹...