「进击 Redis」二十八、确定不了解一下 Cluster 的通讯协议(Gossip)吗?
作者:互联网
前言
掘金七日打卡活动的第四篇,也是关于 Redis 系列的第二十七篇,这一篇的话主要是一起来熟悉Redis cluster
集群模式下的通讯协议。讲道理,这个如果说要对 Redis 研究的深一点那还是很有必要了解一下的。然后,关于cluster
就弄到这了,还有一些像集群的伸缩
、故障恢复
呀就暂时不弄,如果有好哥哥们有想了解的话那就后面再加上去。
上一篇还只会用 @Service 注册 Bean 吗?。单日的浏览量已经到了1351
,点赞数的话是15
,讲道理这还是给了我很大的一个动力,在这里要感谢好哥哥们的支持与关注,猛男我会继续努力的。后面的话应该会弄一个微信公众号,具体的细节弄完在说吧。
概述
确定不了解一下 Redis cluster
的通讯协议吗?其实这一块可以选择不弄的,主要吧cluster
的通讯协议有一个别名,叫做疫情传播算法
或者流行病协议
。受疫情影响,所以就还是一起来了解一下,因为本身我对这一块了解的还是比较少的(我是个只会CRUD
初级攻城狮)。
首先呢,cluster
的通讯协议使用的是Gossip
协议。上面也说了,aka 流行病协议
、疫情传播算法
。为什么这么叫等下看看Gossip
协议对应的原理好哥哥们就懂了。
Gossip
协议是一个去中心化思路的分布式通信协议。Gossip
协议于 1987 年在ACM
上发表的论文Epidemic Algorithms for Replicated Database Maintenance
中被提出,主要用在分布式数据库系统中各个副本节点间的数据同步。这种场景的一个最大特点就是组成网络的节点都是对等的,网络中即使有的节点因宕机而重启,或有新节点加入,但经过一段时间后,这些节点的状态也会与其他节点达成一致,也就是说,Gossip
天然具有分布式容错的优点。
另外Gossip
是一个带冗余的容错算法,是一个最终一致性算法。虽然无法保证在某个时刻所有节点状态一致,但可以保证在最终
(最终
是一个现实中存在,但理论上无法证明的时间点)所有节点一致。实际上Gossip
可以用于众多能接受最终一致性
的领域,比如说失败检测
、路由同步
、Pub/Sub
等。但是Gossip
的缺点也很明显,冗余通信会对网路带宽、CPU
资源造成很大的负载,而这些负载又受限于通信频率,该频率又影响着算法收敛的速度,因此,针对不同的应用场景,也有很多的优化方法。
Gossip
传播消息的过程主要如下图(网图):
注意点
Gossip
过程是由一个种子节点(可以理解成“毒王”)发起,当一个种子节点有状态需要更新到网络中的其他节点时,它会随机
的选择周围几个节点散播消息,收到消息的节点也会重复该过程,直至最终网络中所有的节点都收到了消息。Gossip
过程是异步的,也就是说发消息的节点不会关注对方是否收到,即不等待响应。不管对方有没有收到,它都会每隔1 秒
(假设)向周围节点发消息。异步是它的优点,而消息冗余则是它的缺点。
Cluster 中的 Gossip
Gossip
协议工作原理就是节点彼此不断通信交换信息,一段时间后所有的节点都会知道集群完整的信息。在cluster
中,信息的种类分为ping消息
、pong消息
、meet消息
、fail消息
等(下面会介绍这几种消息), 整体的节点通讯的过程大概如下:
- 集群中的每个节点都会单独开辟一个
TCP
通道,用于节点之间彼此通信,通信端口号在基础端口上加10000
。 - 每个节点在固定周期内通过特定规则选择几个节点发送
ping
消息。 - 接收到
ping消息
的节点用pong消息
作为响应。
集群中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点,也可能仅知道部分节点,只要这些节点彼此可以正常通信,最终它们会达到一致的状态。当节点出故障、新节点加入、主从角色变化、槽信息变更等事件发生时,通过不断的ping/pong
消息通信,经过一段时间后所有的节点都会知道整个集群全部节点的最新状态,从而达到集群状态同步的目的(最终一致性)。
Gossip 消息
Gossip
协议的主要职责就是信息交换。信息交换的载体就是节点彼此发送的Gossip
消息,常用的Gossip
消息就是上面提到的那四种。在cluster
中的每个节点都维护了一份自己视角下的当前整个集群的状态,主要包括:
-
当前集群状态。
-
集群中各节点所负责的
slots
信息,及其migrate
状态。 -
集群中各节点的
master-slave
状态。 -
集群中各节点的存活状态及怀疑
fail
状态。
节点信息通讯模式如下图:
-
meet消息
用于通知新节点加入。消息发送者通知接收者加入到当前集群,meet
消息通信正常完成后,接收节点会加入到集群中并进行周期性的 ping、pong 消息交换。 -
ping消息
是集群内交换最频繁的消息,集群内每个节点每秒向多个其他节点发送ping消息
,用于检测节点是否在线和交换彼此状态信息。ping消息
发送封装了自身节点和部分其他节点的状态数据。 -
pong消息
是当接收到ping
、meet
消息时,作为响应消息回复给发送方确认消息正常通信。pong 消息内部封装了自身状态数据。节点也可以向集群内广播自身的pong消息
来通知整个集群对自身状态进行更新。 -
fail消息
是当节点判定集群内另一个节点下线时,会向集群内广播一个fail消息
,其他节点接收到fail消息
之后把对应节点更新为下线状态。
节点选择
上面已经把常用的消息弄清楚了,在注意点中也提到了Gossip
是随机来选择节点。那cluster
是怎么选择节点的呢?
cluster
集群下节点通信采用固定频率
(定时任务每秒执行 10 次)。因此节点每次选择需要通信的节点列表变得非常重要。通信节点选择过多虽然可以做到信息及时交换但成本过高。节点选择过少会降低集群内所有节点彼此信息交换频率,从而影响故障判定、新节点发现等需求的速度。因此cluster
集群的Gossip
协议需要兼顾信息交换实时性和成本开销。通讯过程如下图:
集群内每个节点维护定时任务默认每秒执行10次
,每秒会随机
选取5个节点
找出最久没有通信的节点发送 ping 消息,用于保证Gossip
信息交换的随机性。每100毫秒
都会扫描本地节点列表,如果发现节点最近一次接受pong消息
的时间大于cluster_node_timeout/2
,则立刻发送ping消息
,防止该节点信息太长时间未更新。
关于这个定时任务是不是很熟悉,在 图解 Redis 哨兵模式 这一篇中就是用了三个定时任务来监控节点的状态,有不熟悉的好哥哥可以翻一翻。
总结
今天这篇的话针对于cluster
的通讯协议写的也不是很深,主要理解一下cluster
是怎么通讯的。对于猛男我来说,对这一块是真的不熟,要不是写博客估计后面很难会学习到。不过呢,这个目前为止我在面试或者工作中还真没有碰到过,一想到下次面试的时候能够吹一波,我的嘴角不经微微的上扬了(嘿嘿嘿…)。
本期就到这啦,欢迎好哥哥们在评论区留言,另外求关注、求点赞
标签:cluster,ping,Redis,Cluster,集群,消息,Gossip,节点 来源: https://blog.csdn.net/qq_34090008/article/details/112663073