Redis Cluster集群

483 阅读6分钟

概述

cluster 是 redis 提供的用来解决单机数据量过大的解决方案。当一台 redis 服务器的内存容量不够时,可以使用 cluster 搭建一套集群并对数据进行分片,将数据散落在不同的机子上。该解决方案和 sentienl 的着重点不同,后者着重于高可用,前者着重于扩展性。

原理

1. 槽位定位算法

redis cluster 没有使用一致性哈希算法,而是采用的哈希槽(hash slot)。

redis 共设置了16384个哈希槽,然后通过 CRC16 算法对 key 进行计算,计算结果对16384取模,获得哈希槽下标,将数据存入对应的哈希槽所代表的服务器中,示意图如下所示:

Redis集群主从、哨兵、Cluster (2).png

Redis Cluster 的客户端来连接集群时,也会得到一份集群的槽位配置信息,这样当客户端要查找某个 key 时,可以直接定位到目标节点。 客户端为了可以直接定位某个具体的 key 所在的节点,需要缓存槽位相关信息,这样才可以准确快速地定位到相应的节点。同时因为可能会存在客户端与服务器存 储槽位的信息不一致的情况,还需要纠正机制来实现槽位信息的校验调整。

2. 跳转

当客户端向某个错误的节点发出了指令后,该节点会发现指令的 key 所在的槽位并不归自己管理 这时它会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去连接这个节点以获取数据。

GET x
- MOVED 3999 127.0.0.1:6381
  • - 表示该指令是一个错误消息。
  • 3999 key 对应的槽位编号
  • 127.0.0.1:6381 目标节点地址。

客户端在收到 MOVED 指令后 要立即纠正本地的槽位映射表。 续所有 key 将使用新的槽位映射表。

3. 迁移

Redis 提供 redis-trib 工具,可以让运维手动调整槽位。

迁移过程

  • Redis 迁移单位是槽
  • 大致迁移流程:从源节点获取内容 → 存到目标节点 → 从源节点删除内容
  • 迁移过程中,会存在新旧槽都存在部分 key 数据
  • 客户端先尝试访问旧节点,如果对应的数据还在旧节点里,旧节点就正常处理。
  • 如果旧节点不存在,要么再新节点里,要么本身就不存在。
  • 旧节点需要确定是哪种情况,所以它会向客户端返回一个 -ASK targetNodeAddr 的重定向指令。
  • 客户端收到这个指令后,先去目标节点执行一个不带参数的 ASKING 指令,然后再目标节点执行原指令。

ASKING 指令的目的就是打开目标节点的选项,告诉它下一条指令不能不理,而要当成自己的槽位来处理。因为在迁移没有完成成之前,按理说这个槽位还是不归新节点管理的,节点是不认的。

4. 容错

Redis cluster每个主节点可以设置若干个从节点,当主节点发生故障,集群就会向某个从节点来提升为主节点。如果没有从节点,故障发生时,整个集群是不可用状态。

Redis也考虑到了这一点,提供了参数 cluster-require-full-coverage

cluster-require-full-coverage: yes

默认值 yes , 即需要集群完整性,方可对外提供服务。如果你想这个时候,还让 redis 对外提供服务,设置为 no 即可。

5. 网络抖动

机房网络难免出现网络抖动,会在一瞬间网络不可用,造成集群之前网络暂时性中断。 Redis cluster 提供了一个 cluster-node-timeout 选项

cluster-node-timeout 30000

如上配置表示,超过 30s 的失联,才可以认定节点出现故障,才会对主从进行切换,如果没有这个选项,主动切换会非常频繁

cluster-slave-validity-factor 10

在进行故障转移的时候全部 slave 都会请求申请为 master,但是有些 slave 可能与 master 断开连接一段时间了导致数据过于陈旧,不应该被提升为 master。该参数就是用来判断slave节点与 master 断线的时间是否过长。

判断方法是:比较 slave 断开连接的时间和

(cluster-node-timeout * cluster-slave-validity-factor) + repl-ping-slave-period 

假设默认的 repl-ping-slave-period10 秒,即如果超过 (30 * 10) + 10 = 310slave 将不会尝试进行故障转移

6. 可能下线与确定下线

Redis cluster 是一个去中心话的项目,某个节点失联并不代表它确定不在线,需要集群之间的协商。

  • 可能下线 PFail:一个节点发现某个节点失联了,即可能下线
  • 确定下线 Fail:一个节点发现某节点可能下线后,会向整个集群广播,其他节点会尝试对此节点进行通信,如果大数据节点认为此节点下线,即确定下线

确定下面后,会向整个集群广播,强迫其他节点也接受改节点下线的事实,进行主从切换。

7. 槽位迁移感知

上面我们介绍,MOVEDASKING 用来返回新的槽位重定向地址。再一定场景可能会重试2次或者多次,所以客户端提供了一个重试次数的参数。

8. 集群变更感知

当服务器节点变更时,客户端应该即时得到通知以实时刷新自己的节点关系表。那客户端是如何得到通知的呢?这里要分 2 种情况:

  • 目标节点挂掉了,客户端会抛出一个 ConnectionError,紧接着会随机挑一个节点来重试,这时被重试的节点会通过 moved error 告知目标槽位被分配到的新的节点地址。
  • 运维手动修改了集群信息,将 master 切换到其它节点,并将旧的 master 移除集群。这时打在旧节点上的指令会收到一个 ClusterDown 的错误,告知当前节点所在集群不可用 (当前节点已经被孤立了,它不再属于之前的集群)。这时客户端就会关闭所有的连接,清空槽位映射关系表,然后向上层抛错。待下一条指令过来时,就会重新尝试初始化节点信息。