【Redis实现系列】通知功能实现

通知

订阅命令

这个功能可以让客户端通过订阅给定的"键空间"或者”事件“,来获知数据库中键的变化,以及数据库中命令的执行情况。

  • 订阅键空间通知: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命令对数据库进行修改之后,服务器会根据配置向客户端发送数据库通知。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:C马雯娟 返回首页