通知
订阅命令
这个功能可以让客户端通过订阅给定的"键空间"或者”事件“,来获知数据库中键的变化,以及数据库中命令的执行情况。
- 订阅键空间通知:
SUBSCRIBE _ _keyspace@<dbid>_ _:<keyname>
- 订阅键事件通知:
SUBSCRIBE _ _keyevent@<dbid>_ _:<eventname>
- 注意:服务器配置的 notify-keyspace-events 选项决定了服务器允许发送哪类通知
- 想让服务器发送所有类型的 键空间通知 和 键事件通知 ,可以将选项的值设置为AKE。
- 想让服务器发送所有类型的 键空间通知,可以将选项的值设置为AK。
- 想让服务器发送所有类型的 键事件通知,可以将选项的值设置为AE。
- 想让服务器只发送和 字符串键有关的键空间通知,可以将选项的值设置为K$。
- 想让服务器只发送和 列表键有关的键事件通知,可以将选项的值设置为El。
操作后发送通知
-
每当一个Redis命令需要发送数据库通知的时候,该命令的实现函数就会调用notify-KeyspaceEvent函数
/** * type :当前想要发送的通知的类型,程序会根据这个值来判断通知是否就是服务器配置 * notify-keyspace-events 选项所允许的通知类型,从而决定是否发送通知。 * * event:事件的名称 * keys:产生事件的键 * dbid:事件的数据库号码 * * 会根据type参数以及这三个参数来构建事件通知的内容,以及接收通知的频道名 */ void notifyKeyspaceEvent(int type,char *event,robj *key,int dbid);
-
示例:SADD命令
void saddCommand(redisClient*c){ // ... // 如果至少有一个元素被成功添加,那么执行以下程序 if (added) { // ... // 发送事件通知 // 类型为REDIS_NOTIFY_SET(表示这是一个集合键通知),名称为sadd(表示这是执行SADD命令所产生的通知) notifyKeyspaceEvent(REDIS_NOTIFY_SET,"sadd",c->argv[1],c->db->id); } // ... }
-
示例:DEL命令
voi delCommand(redisClient *c){ int deleted=0,j; // 遍历所有输入键 for (j=1; j<c->argc; j++){ // 尝试删除键 if (dbDelete(c->db,c->argv[j])){ // ... // 删除键成功,发送通知 // 类型为REDIS_NOTIFY_GENERIC(表示这是一个通用类型的通知),名称为del(表示这是执行DEL命令所产生的通知) notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",c->argv[j],c->db->id); // ... } } // ... }
发送通知实现
notifyKeyspaceEvent函数执行以下操作
- server.notify_keyspace_events属性就是服务器配置notify-keyspace-events选项所设置的值,如果给定的通知类型type不是服务器允许发送的通知类型,那么函数会直接返回,不做任何动作。
- 如果给定的通知是服务器允许发送的通知,那么下一步函数会检测服务器是否允许发送键空间通知,如果允许的话,程序就会构建并发送事件通知。
- 最后,函数检测服务器是否允许发送键事件通知,如果允许的话,程序就会构建并发送事件通知。
以下是notifyKeyspaceEvent函数的伪代码实现:
def notifyKeyspaceEvent(type, event, key, dbid):
# 如果给定的通知不是服务器允许发送的通知,那么直接返回
if not(server.notify_keyspace_events & type):
return
# 发送键空间通知
if server.notify_keyspace_events & REDIS_NOTIFY_KEYSPACE:
#将通知发送给频道__keyspace@<dbid>__:<key>
#内容为键所发生的事件 <event>
# 构建频道名字
chan = "__keyspace@{dbid}__:{key}".format(dbid=dbid, key=key)
# 发送通知
pubsubPublishMessage(chan, event)
# 发送键事件通知
if server.notify_keyspace_events & REDIS_NOTIFY_KEYEVENT:
# 将通知发送给频道__keyevent@<dbid>__:<event>
# 内容为发生事件的键 <key>
# 构建频道名字
chan = "__keyevent@{dbid}__:{event}".format(dbid=dbid,event=event)
# 发送通知
pubsubPublishMessage(chan, key)
小结
当Redis命令对数据库进行修改之后,服务器会根据配置向客户端发送数据库通知。