• Kaito
    2021-10-09
    1、哨兵是通过 master 的 PubSub 发现其它哨兵的:每个哨兵向 master 的 PubSub(__sentinel__:hello 频道)发布消息,同时也会订阅这个频道,这样每个哨兵就能拿到其它哨兵的 IP、端口等信息 2、每个哨兵有了其它哨兵的信息后,在判定 Redis 实例状态时,就可以互相通信、交换信息,共同判定实例是否真的故障 3、哨兵判定 Redis 实例故障、发起切换时,都会向 master 的 PubSub 的频道发布消息 4、客户端可以订阅 master 的 PubSub,感知到哨兵工作到了哪个状态节点,从而作出自己的反应 5、PubSub 的实现,其实就是 Redis 在内存中维护了一个「发布-订阅」映射表,订阅者执行 SUBSCRIBE 命令,Redis 会把订阅者加入到指定频道的「链表」下。发布者执行 PUBLISH,Redis 就找到这个映射表中这个频道的所有「订阅者」,把消息「实时转发」给这些订阅者 课后题:在哨兵实例上执行 publish 命令,这条命令是不是就是由 pubsub.c 文件中的 publishCommand 函数来处理的? 以哨兵模式启动的 Redis 实例,会使用新「命令表」。 在 server.c 的 main 函数中可以看到,哨兵模式启动后,会调用 initSentinel 函数。 void initSentinel(void) { ... // 只添加 sentinelcmds 下的命令 for (j = 0; j < sizeof(sentinelcmds)/sizeof(sentinelcmds[0]); j++) { int retval; struct redisCommand *cmd = sentinelcmds+j; retval = dictAdd(server.commands, sdsnew(cmd->name), cmd); serverAssert(retval == DICT_OK); } ... } 可以看到只把 sentinelcmds 命令表添加到了 server.commands 中。sentinelcmds 如下: struct redisCommand sentinelcmds[] = { ... {"subscribe",subscribeCommand,-2,"",0,NULL,0,0,0,0,0}, {"publish",sentinelPublishCommand,3,"",0,NULL,0,0,0,0,0}, {"info",sentinelInfoCommand,-1,"",0,NULL,0,0,0,0,0}, ... }; 可以看到哨兵的 PUBLISH 命令是由 sentinelPublishCommand 单独实现的,并非普通实例的 publishCommand。
    展开
    共 1 条评论
    5
  • 曾轼麟
    2021-09-30
    回答老师的问题:这条命令是不是就是由 pubsub.c 文件中的 publishCommand 函数来处理的呢? 答:并不是publishCommand来执行的 在《哨兵也和Redis一样实例化吗?》这篇文章老师有提到,哨兵模式启动的时候,会把 server.commands 对应的命令表清空,然后在其中添加哨兵对应的命令。所以最后执行的应该是哨兵的 publish 命令,对应的执行函数应该是 sentinelPublishCommand,发送的应该也只是hello频道。 总结: 本篇文章,老师重点介绍了Pub/Sub在主从切换中的作用,以及Pub/Sub是如何初始化的,在redis中,实现发布的函数是 pubsubPublishMessage,而订阅的主要函数是 pubsubSubscribeChannel。 在哨兵模式下是通过 sentinelEvent 的方式进行发布的,其调用流程是 sentinelEvent -> pubsubPublishMessage,而哨兵实例的 publish 命令被替换,是通过 sentinelProcessHelloMessage -> sentinelProcessHelloMessage 向其它实例发送 hello 频道的消息,用于同步哨兵实例的基本信息,比如 IP、端口号、quorum 阈值等。
    展开
    
    5
  • fkc_zyk
    2023-05-19 来自广东
    addReplyBulk(c,channel); addReplyBulk(c,message);这两个方法读取的全局数据是什么,分别有什么作用,感觉这两个都是读取订阅列表的客户端实现消息的发送
    
    