Redis 支持簡單的 pub/sub 功能,之所以說其簡單,是因爲消息是發送即遺忘的(fire and forgot),不會進行持久化,一旦宕機,消息丟失。
客戶端可以使用兩種方式訂閱消息:
- 頻道(channel)
- 模式(pattern)
頻道是最簡單和核心的方式,模式是基於頻道的模式匹配。例如:現有頻道 "it.news" 和 "it.post" ,客戶端可以直接訂閱 "it.new",或者可以訂閱模式 "it.*" 從而在頻道 "it.news" 和 "it.post"有消息時得到通知。
深入 Redis 源代碼(branch: 6.0)來探究 Redis pub/sub 功能的實現。
在 redisServer 和 client 中包含了 pubsub_channels 和 pubsub_patterns,如下(server.h):
struct redisServer {
dict *pubsub_channels;
list *pubsub_patterns;
dict *pubsub_patterns_dict;
// ...
}
typedef struct client {
dict *pubsub_channels;
list *pubsub_patterns;
// ...
} client;
typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next;
} dictEntry;
typedef struct dictht {
dictEntry **table;
// ...
} dictht;
typedef struct dict {
dictType *type;
dictht ht[2];
// ...
} dict;
typedef struct list {
listNode *head;
listNode *tail;
unsigned long len;
// ...
} list;
typedef struct pubsubPattern{
client *client;
robj *pattern;
} pubsubPattern;
pubsub_channels 是字典類型(見 dict.c),內部實現是哈希表(hash table),鍵爲 channel,值爲訂閱該頻道的客戶端列表 clients。
pubsub_patterns 是一個列表類型(見 adlist.h),內部實現是雙向鏈表,元素爲 pubsubPattern,pubsubPattern 包含 glob匹配模式(通配符匹配模式,廣泛運用於 Linux 中的 ls、find、mv 等等命令,git 中的 .gitignore 文件中) pattern 和訂閱了該匹配模式客戶端 client。