Redis Cluster Spec

目录 #

设计目标和基本原理[bing] #

高性能和线性扩展 #

Redis集群可以支持到1000个节点,使用异步复制和无代理的架构,避免了值合并的开销。

可接受的写安全性 #

Redis集群尽力保留与大多数主节点连接的客户端的写操作,但在分区窗口期内可能会丢失已确认的写操作

可用性 #

Redis集群可以在大多数主节点可达且每个不可达主节点至少有一个可达副本的情况下存活,并且可以通过副本迁移来提高抗故障能力。

哈希槽分配 #

Redis集群将16384个哈希槽分配给不同的主节点,每个主节点负责存储和服务一部分哈希槽。客户端可以通过计算键的CRC16值对16384取模来得到对应的哈希槽。也可以使用哈希标签来强制将多个键分配到同一个哈希槽,以支持多键操作。

节点间通信 #

Redis集群节点之间使用一个TCP端口和一个二进制协议进行通信,称为集群总线。每个节点都与其他所有节点连接,使用gossip协议来传播集群的信息,如新节点、故障节点、配置变化等。

客户端重定向 #

Redis集群节点不会代理请求,而是根据自己的哈希槽映射表,将客户端重定向到正确的节点。客户端可能收到MOVED或ASK错误,表示需要重新发送请求到另一个节点。MOVED表示哈希槽被永久地分配给了另一个节点,ASK表示哈希槽正在被迁移,需要发送ASKING命令后再发送请求。

哈希槽迁移 #

Redis集群支持在运行时添加和删除节点,这是通过将哈希槽从一个节点移动到另一个节点来实现的。迁移过程中,源节点会将接收到的关于该哈希槽的请求重定向到目标节点,或者直接处理已存在键的请求。目标节点会接收到源节点通过MIGRATE命令发送过来的键,并在迁移完成后更新自己的配置。

故障检测和副本提升 #

Redis集群使用心跳包和gossip协议来检测节点是否可达,并使用PFAIL和FAIL两种标志来表示故障状态。当一个主节点被大多数主节点标记为FAIL时,它的一个副本会发起选举并请求投票。如果获得了大多数主节点的授权,该副本会提升为主节点,并生成一个新的配置版本号(configEpoch)。

副本选举和配置传播的机制[bing] #

副本选举 #

当一个主节点失效时,它的一个副本会尝试发起选举,向其他主节点发送授权请求。如果获得了大多数主节点的回复,它就赢得了选举,并获得了一个新的唯一的配置版本号(configEpoch)。它会开始以主节点的身份广播心跳包,并通知其他节点更新配置。

配置传播 #

当一个节点收到一个心跳包或UPDATE消息时,它会根据一些规则来更新自己的哈希槽映射表。如果一个哈希槽是未分配的,或者有一个新的节点使用更高的configEpoch来声明它,那么接收者会将该哈希槽绑定到新的节点。这样可以保证最后一次故障转移胜出,并且所有节点最终会达成一致。

节点重置和遗忘 #

当一个节点需要从一个集群中移除或加入到另一个集群时,可以使用CLUSTER RESET命令来重置它的状态。这个命令有两种模式:软重置和硬重置。软重置会保留当前的configEpoch,而硬重置会将其设置为0。当一个节点被移除后,其他节点需要使用CLUSTER FORGET命令来删除它在节点表中的条目,并设置一个60秒的禁止期,防止因为gossip协议而重新添加它。

发布订阅 #

Redis集群支持发布订阅功能,客户端可以向任何节点发送SUBSCRIBE或PUBLISH命令。集群会将发布的消息转发到所有其他节点。Redis 7.0及以后版本还支持分片发布订阅功能,其中分片频道根据与键相同的算法分配到哈希槽。分片消息必须发送到拥有该哈希槽的节点,集群会将发布的分片消息转发到该哈希槽所在的分片中的所有节点。

CRC16算法 #

这篇文章最后给出了计算键对应哈希槽的CRC16算法的C语言实现代码。这个算法使用了1021作为多项式,并且不反转输入输出字节。

参考 #

Redis cluster specification ***