《Redis设计与实现》读书笔记(三十一) ——Redis集群消息类型

《Redis设计与实现》读书笔记(三十一) ——Redis集群消息类型

(原创内容,转载请注明来源,谢谢)

1、发送消息类型

集群中节点通过发送与接收消息进行通信。

发送消息的节点称为消息发送者,接收消息节点称为接收者。消息发送类型如下:

1)meet

当客户端发送clustermeet给节点,节点会发送meet消息给接收者,请求接收者加入到发送者当前的集群中。

2)ping

每个节点每秒,默认会随机从当前已知节点列表,挑选5个节点,并从中挑选最久未发送过ping消息的节点,对其发送ping,检测其是否在线。

另外,如果某个节点最后一次回复pong的时间,距离当前时间,已经超过redis配置文件中cluster-node-timeout设定的秒数的一半,则也会对该节点发送ping,防止多次没有随机到该节点,导致对该节点的状态更新过慢。

3)pong

当节点收到meet或者ping,为了告知发送者收到消息,会回复pong。

另外,完成一次故障转移后,新的主节点会给向集群广播pong。

4)fail

当节点认为某个节点下线,会向集群广播关于该节点的fail状态,其他节点接收到后,都会将该节点状态置为下线。

5)publish

当节点收到publish命令,会执行该命令,并向集群发送publish,其他节点收到后也会执行该命令。

2、消息头

所有消息都由消息头包裹,消息头可以认为是消息的一部分。消息头由cluster.h/clusterMsg结构记录,如下:

         structclusterMsg{
         uint32_t totlen;//消息总长度,包括消息头长度和正文长度
         uint16_t type;//消息类型
         uint16_t count;//消息正文包含节点信息数量,只有在meet、ping、pong这三种涉及到gossip协议的类型使用
         uint64_t currentEpoch;//发送者的配置纪元
uint64_t configEpoch;//该节点是主节点时,是发送者的配置纪元;是从节点时,是对应正在复制的主节点的配置纪元
         char sender[REDIS_CLUSTER_NAMELEN];//发送者名字(ID)
         unsigned char myslots[REDIS_CLUSTER_SLOTS/8];//发送者目前的槽信息
         char slaveof[REDIS_CLUSTER_NAMELEN];//主节点时记录的是40位长的都是0的字符串,从节点时记录的是复制的主节点的名字
         uint16_t port;//发送者端口号
         uint16_t flag;//发送者标识值
         unsigned char state;//发送者所处的集群状态
         union clusterMsgData data;//消息的正文
}clusterMsg;

消息的正文是一个联合体,共有三种类型结构体,包括ping、fail、publish,其中pong、meet类型都和ping一样。

3、meet、ping、pong

这三个的类型一样,都是记录在联合体clusterMsgData中的结构体。因为这三种消息有相同的正文,节点是通过消息头的type判断是这三种的哪一种。

这三种消息的类型是clusterMsgDataPublish,这是一个结构体,记录节点名字、最后给该节点发送ping的时间戳、最后收到节点pong的时间戳、节点ip、端口号、标识等。

当节点接收到信息时,如果不认识里面的节点,则会与节点进行握手,如果认识则更新对应的信息。

4、fail

由于使用gossip协议会有延迟,fail是用来表示该节点下线,需要尽快传达,因此不用gossip协议,而是立即让集群中的全部节点知情。其正文就是下线节点的名字。

5、publish

客户端向集群发送publish<channel> <message>,接收的频道不仅会向频道channel发送message,还会向集群广播publish,其他节点也会执行该命令。

因此,向某个节点发送publish,会导致所有节点都执行该命令。

具体流程如下:

publish用结构体clusterMsgDataPublish记录,内容是包括频道长度,消息长度,以及具体内容。

其中,bulk_data的前channel_len字节,记录channel参数;剩余字节记录message参数。

例如,发送publish“news.it” “hello” 如下:

其实也可以直接向集群广播publish命令,但是由于其不符合redis设计的各节点通过消息发送和接收来传播消息的做法,因此采用对某一节点进行消息发送。

——written by linhxx 2017.09.18

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-09-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器之心

资源 | 忘了Python关键语句?这份备忘录拯救你的记忆

Python 3 Cheat Sheet 一共包含两页,分成了多个框图,涉及基本的 Python 数据结构、数学运算、条件和循环语句、文件读写,以及异常值处理等...

903
来自专栏进击的程序猿

袖珍分布式系统(四)

本文是Distributed systems for fun and profit的第四部分,本文是阅读该文后的一些记录。

592
来自专栏Android机动车

Socket TCP协议 实时通信的粘包处理之Java与C++实现

详细内容请阅读 http://blog.csdn.net/zhangxinrun/article/details/6721495

1092
来自专栏用户2442861的专栏

网易2013校园招聘笔试题详解

http://blog.csdn.net/silangquan/article/details/18142651

952
来自专栏java达人

哈希表

哈希表是种数据结构,它可以提供快速的插入操作和查找操作。第一次接触哈希表时,它的优点多得让人难以置信。不论哈希表中有多少数据,插入和删除(有时包括侧除)只需要接...

1667
来自专栏C语言及其他语言

【蓝桥杯系列】第一节 C的基本用法

置顶编程范收获更多热门编程快讯 大家好,最近很多小伙伴向我反应小编!我参加了蓝桥杯但是我连那是什么都不知道,我该怎么训练?是不是在网站刷题就可以啊? 在这里我要...

3107
来自专栏我的博客

Laravel 辅助函数

array_add() 如果给定的键不在数组中,会把给定的键值对加到数组中.否则则不加入 array_divide() 函数返回两个数组,一个包含原本数组的键...

26410
来自专栏从流域到海域

《笨办法学Python》 第28课手记

《本办法学Python》 第28课手记 本节课为布尔表达式的练习课。 作者在本课给出了将复杂的表达式逐级降解为一个单一结果,请记住那个流程。 本节课我将不会给出...

1727
来自专栏Python疯子

TebsorFlow基本语法

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invi...

752
来自专栏机器学习从入门到成神

牛客网刷题汇总(一)附解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

1392

扫码关注云+社区