这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战
Redis数据库的通知机制
发送通知
某个键执行了什么命令的通知为键空间通知,某个命令被哪个键执行了是键事件通知。
发送数据库的通知由notify.c 的notifyKeyspaceEvent 实现
通知类型通过notify-keyspace-events属性来配置:
发送所有类型的键空间通知和键事件通知,设置值AKE
发送所有类型的键空间通知,设置值AK
发送所有类型的键事件通知,设置值AE
只发送和字符串键有关的键空间,设置值K$
只发送和列表键有关的键事件通知,可以将选项的值设置为El
void notifyKeyspaceEvent(int type, char *event, robj *key, int dbid) {
sds chan;
robj *chanobj, *eventobj;
int len = -1;
char buf[24];
/* If any modules are interested in events, notify the module system now.
* This bypasses the notifications configuration, but the module engine
* will only call event subscribers if the event type matches the types
* they are interested in. */
moduleNotifyKeyspaceEvent(type, event, key, dbid);
/* If notifications for this class of events are off, return ASAP. */
if (!(server.notify_keyspace_events & type)) return;
eventobj = createStringObject(event,strlen(event));
/* __keyspace@<db>__:<key> <event> notifications. */
if (server.notify_keyspace_events & NOTIFY_KEYSPACE) {
chan = sdsnewlen("__keyspace@",11);
len = ll2string(buf,sizeof(buf),dbid);
chan = sdscatlen(chan, buf, len);
chan = sdscatlen(chan, "__:", 3);
chan = sdscatsds(chan, key->ptr);
chanobj = createObject(OBJ_STRING, chan);
pubsubPublishMessage(chanobj, eventobj);
decrRefCount(chanobj);
}
/* __keyevent@<db>__:<event> <key> notifications. */
if (server.notify_keyspace_events & NOTIFY_KEYEVENT) {
chan = sdsnewlen("__keyevent@",11);
if (len == -1) len = ll2string(buf,sizeof(buf),dbid);
chan = sdscatlen(chan, buf, len);
chan = sdscatlen(chan, "__:", 3);
chan = sdscatsds(chan, eventobj->ptr);
chanobj = createObject(OBJ_STRING, chan);
pubsubPublishMessage(chanobj, key);
decrRefCount(chanobj);
}
decrRefCount(eventobj);
}
type 为当前发送的通知类型,event 是事件名称,key 为产生事件的键,dbid 是产生事件的数据库号码
根据这几个参数构建事件通知的内容,已经接收通知的频道
- server.notify_keyspace_events 为服务器配置的notify-keyspace-events 属性值,如果给定的通知类型type 不是服务器允许发送的通知类型,函数直接返回
- 如果给定的通知是服务器允许发送的通知,判断服务器是否允许发送键空间通知,如果允许,程序构建和发送事件通知
- 判断是否允许发送键事件通知,如果允许,发送事件通知