RedisCluster 集群实现原理

1. RedisCluster 的架构

要支持集群首先要克服数据分片问题,也就是一致性哈希问题,常见方案有以下几种:

  1. 客户端分片
    使用类似于哈希取模的做法,当客户端对服务端的数量完全掌握和控制时,可以简单使用
  2. 中间层分片
    在客户端和服务器端之间增加中间层,充当管理者和调度者,客户端的请求打向中间层,由中间层实现请求的转发和响应的回收,中间层最重要的作用是对多台服务器的动态管理
  3. 服务端分片
    实现去中心化的管理模式,客户端直接向服务器中任意结点请求,如果被请求的节点没有所需数据,则向客户端回复MOVED,并告诉客户端所需数据的存储位置,这个过程实际上是客户端和服务端共同配合,进行请求重定向来完成的

Redis 3.0 版本之后,Redis 支持 RedisCluster集群作为分布式解决方案。该集群采用多主多从结构,实现了服务端的分片技术,使用多个 Master节点保存数据和整个集群状态,通过增减 Master节点就能达到增大/缩小 Redis 数据容量的目的,从而很好地支持横向扩容官方传送门

在这里插入图片描述

Redis Cluster 集群的结构特点如下:

  1. 集群内支持多个 Master 节点,每个 Master 节点也可以有多个 Slave 节点。所有节点彼此连接(基于PING-PONG机制),内部使用二进制协议通信
  2. 集群中超过半数的节点检测到某个节点失效时才判定该节点下线
  3. 客户端与集群中任意一个可用 Master 节点直连
  4. 集群内置数据自动分片机制,将集群内部所有的 key 映射到16384个Slot中,每个 Master 节点都会记录哪些 Slot 指派给了自己,哪些指派给了其他节点。这种机制让集群内节点的增加和移除很简单,增加一个 Master 节点就将其他节点的 Slot 移动部分过去,减少一个Master 就将它的 Slot 移动到其他节点即可,移动 Slot 的成本是非常低的
  5. 客户端连接集群中任意 Master 节点即可发送命令,不过在命令执行之前会根据 key 使用CRC16(key)%16384定位到一个 Slot,如果该 Slot 不在当前 Master 节点的负责范围内,则当前节点会将负责该 Slot 的节点地址返回给客户端,客户端收到后自动将原请求重新发往目标节点

RedisCluster 设计成 16384 个 Slot 的原因

可参考 作者的回答,主要有以下几个方面的考虑

  1. 心跳包的大小
    因为 redis 节点需要定时发送一定数量的 ping 消息作为心跳包,而在包的消息头中最占空间的是 myslots[CLUSTER_SLOTS/8]如果 Slot 数量太大,如 65536,则这块的大小是: 65536÷8=8kb,ping 消息的消息头太大了,浪费带宽
  2. 集群节点数量有限
    集群节点越多心跳包的消息体内携带的数据越多,如果节点数量超过一定限制,也会导致网络拥堵,从而使集群内节点达到最终一致性的时间相对变长,因此不建议集群内节点数量超过1000个,在这样的情况下,16384个 Slot 足够使用
  3. 传输效率
    Redis 主节点的配置信息中,其负责的 Slot 通过一个 bitmap 位图来保存。在网络传输过程中,bitmap 会被压缩,但是如果 bitmap 的填充率 slots/N(N表示节点数)很高的话,bitmap 的压缩率就很低。在节点数量有限的情况下,Slot 数量尽量小可以提高 bitmap 的压缩率,从而减少网络流量

2. 集群内部节点数据一致性实现

2.1 RedisCluster 节点间通信方式

RedisCluster 集群内每个 Master 节点会使用两个端口,一个是提供服务的端口,比如 6379,另外一个是该端口号加10000的端口号,比如16379,这个端口号是专门用来进行节点间通信的,也就是集群总线

RedisCluster 不是将集群元数据(节点信息,故障信息,节点的增加和移除,slot信息等)集中存储在单个节点上,而是在所有节点间采取Gossip协议不断进行通信的方式保持集群中每个节点上的元数据的一致性。具体来说,就是每个节点每隔一段时间都会往另外几个节点发送 PING 消息,其他节点接收到 PING 之后返回 PONG 消息,互相交换集群节点数据

  • Gossip 优点
    元数据的更新比较分散,不是集中在一个节点,更新请求会陆续打到所有节点上去更新,有一定的延时,降低了压力
  • Gossip 缺点
    元数据更新有延时,可能导致集群的一些变化在各个节点上存在一段时间的同步滞后

2.2 Gossip 协议

Gossip协议又被称为流言协议,是 Redis 集群各个节点彼此同步状态的手段。其工作方式很简单,以加入新节点(Meet) 为例,最初只有发出邀请的节点和被邀请节点知道这件事,但是通过 Ping 消息一层一层扩散,其他节点也被通知到了,这样Gossip协议实现了最终一致性

Gossip 算法又被称为反熵(Anti-Entropy),就是在混乱中寻求一致,这也说明了Gossip 的特点:在一个有界网络中,每个节点可能知道所有其他节点,也可能仅知道几个邻居节点,只要这些节点可以通过网络连通,并且每个节点都随机地与其他节点通信,那么经过一段时间的交流,最终所有节点的状态都会达成一致

RedisCluster 的集群消息主要有以下几种类型:

  1. MEET
    通过cluster meet ip port命令,已有集群的某个节点会向新加入的节点发送邀请,使其加入现有集群
  2. PING
    每个节点都会频繁地给其他节点发送 Ping,每次会选择5个最久没有通信的其他节点,如果发现某个节点通信延时达到了cluster_node_timeout/2,那么立即发送 Ping,避免数据长时间不一致。cluster_node_timeout可以用来调节 Ping 的频率,如果该值设置得比较大,那么会减少 Ping 次数。Ping 消息中包含了节点自己的状态及其维护的集群元数据,还会带上至少3个已知的其他节点信息一起发送出去,进行数据交换
  3. PONG
    节点收到 Ping 消息后会回复 Pong 消息,消息中同样带有自己节点的信息及已知的其他节点信息
  4. FAIL
    某节点判定一个节点 Fail 后,会立即向集群所有节点广播该节点挂掉的消息,其他节点收到消息后标记指定的节点已下线
  5. PUBLISH
    当节点接收到一个 PUBLISH 命令时,节点会执行这个命令,并向集群广播一条 Publish 消息,所有接收到消息的节点都会执行相同的 PUBLISH 命令
  6. FAILOVER_AUTH_REQUEST
    当 Master 节点进入 Fail 状态,Slave 向集群中的所有的节点发送消息,但是只有 Master 才能给 Slave 投票failover 其的 Master
  7. FAILOVER_AUTH_ACK
    当 Master 接收到 FAILOVER_AUTH_REQUEST 消息,如果 Slave 节点满足投票条件且 Master 自己在当前纪元未投票就返回 FAILOVER_AUTH_ACK 消息给 Slave 投票

3. 高可用性原理

RedisCluster 高可用的原理和哨兵机制极其相似,主要原理如下:

  1. Master 节点宕机判定
    如果一个节点 ping 了另外一个节点,这个节点在cluster-node-timeout超时时间内一直没有返回 pong,那么就被认为 PFAIL ,主观宕机
    如果一个节点认为某个节点 PFAIL 了,那么会在 ping 消息中将这个信息广播给其他节点,如果多个节点(N/2 + 1)都认为目标节点 PFAIL了,那么这个节点就会变成 FAIL,客观宕机
  2. Slave 节点切换为 Master 节点
    对宕机的 Master 节点,需要从其所有的从节点中选择一个切换成 Master 节点。这个过程中大概分为了 3 个步骤:
    1. 过滤可用的 Slave 节点
      具体做法就是检查每个 Slave 节点与 Master 节点断开连接的时间,如果超过了cluster-node-timeout * cluster-slave-validity-factor,那这个Slave 节点就没有资格切换成 Master
    2. 确定候选节点优先级
      过滤出可用的 Slave 节点后,所有从节点需要进行排序,排序因子为 复制偏移量 offset ,每个从节点根据优先级设置一个选举时间,选举时间靠前的 Slave 节点优先进行选举
    3. 选举出 Master 节点
      Slave 节点将自己记录的集群 currentEpoch 加1,并广播 Failover Request信息。其他节点收到该信息,只有 Master 节点会判断请求者的合法性,发送FAILOVER_AUTH_ACK 对 Slave 节点进行选举投票,每一个epoch只发送一次ack。Slave 节点收集 FAILOVER_AUTH_ACK,如果大部分Master节点(N/2 + 1)都投票给了这个 Slave 节点,那么选举通过,这个 Slave 节点将执行主备切换,切换为新的 Master 节点,并广播通知集群其它节点
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值