目录
1. 全量同步(Full Resynchronization)
2. 增量同步(Incremental Replication)
主从复制(Replication)模式:
哨兵(Sentinel)模式:
Cluster(集群)模式:
主从复制可以根据需要分为全量同步的增量同步两种方式。
Redis 全量复制一般发生在 slave 的初始阶段,这时 slave 需要将 master 上的数据都复制一份,具体步骤如下:

增量复制实际上就是在 slave 初始化完成后开始正常工作时 master 发生写操作同步到 slave 的过程。增量复制的过程主要是 master 每执行一个写命令就会向 slave 发送相同的写命令,slave 接受并执行写命令,从而保持主从一致。
当从节点初次连接主节点或断线后重新连接且无法进行部分同步时,主节点执行 BGSAVE 命令生成 RDB 快照,并将其发送给从节点。从节点加载 RDB 快照以快速恢复大部分数据。接着,主节点将断线期间积累的写命令(存储在复制积压缓冲区中)发送给从节点,从节点执行这些命令以达到与主节点的完全同步。
部分同步(Partial Resynchronization):一旦从节点完成全量复制并进入正常工作状态,主从节点之间采用增量复制进行持续同步。主节点在执行完客户端的写操作后,将这些命令通过命令传播机制发送给所有从节点。从节点接收到命令后在本地执行,保持与主节点的实时同步。
复制偏移量(Replication Offset):主从节点各自维护一个复制偏移量,表示已复制命令的字节数。每当主节点向从节点发送一个命令时,双方都会更新自己的偏移量。通过比较偏移量,主从节点可以判断复制进度和是否存在数据差距。
复制积压缓冲区(Replication Backlog):主节点维护一个固定长度的先进先出(FIFO)队列,存储最近一段时间的写命令。当从节点断线重连时,如果复制积压缓冲区中仍保留了断线期间的命令,从节点可以请求这部分命令进行部分同步,避免进行耗时的全量复制。
一致性 hash 其实是普通 hash 算法的改良版,其 hash 计算方法没有变化,但是 hash 空间发生了变化,由原来的线性的变成了环。
缓存 key 通过 hash 计算之后得到在 hash 环中的位置,然后顺时针方向找到第一个节点,这个节点就是存放 key 的节点。
哈希环:将整个哈希值空间组织成一个虚拟的环状结构,通常是一个0到2^32-1的整数环。每个节点(Redis 实例)和数据键(key)都通过相同的哈希函数映射到这个环上。
节点映射:每个 Redis 节点通过其标识符(如 IP 地址、端口号或节点ID)计算出一个哈希值,将该值映射到哈希环上。在 Redis Cluster 中,使用的是“哈希槽(hash slot)”的概念,将整个哈希环划分为固定数量(如16384个)的槽位,每个节点负责一部分槽位。
数据映射:对于要存储或查询的数据键,同样通过哈希函数计算其哈希值,并定位到哈希环上的一个位置。然后沿着环顺时针方向查找第一个遇到的节点(或槽位),该节点即为该数据键应当存储或查询的目标节点。
节点加入:当新增一个节点时,它会接管一部分哈希槽。这些槽位可能是从其他节点转移过来的,也可能是在创建集群时预先分配给新节点的。由于每个槽位对应的数据范围是确定的,因此只需要将原来映射到这些槽位上的数据迁移到新节点即可,影响范围有限。
节点移除或故障:当节点离开集群或发生故障时,其负责的哈希槽需要被其他节点接管。由于数据已经按照槽位均匀分布,其他节点只需接管对应的槽位,就能继续提供服务,受影响的数据同样仅限于那些槽位对应的范围。
为了进一步提高数据分布的均匀性和应对节点性能差异,Redis Cluster 在实现中通常会使用虚拟节点(Virtual Node)的概念。每个物理节点对应多个虚拟节点,每个虚拟节点有自己的哈希值并映射到哈希环上。这样,即使实际节点数量较少,也能通过虚拟节点在环上形成更为均匀的分布,从而减少数据迁移时的波动。
Redis 客户端在连接集群时,通常会获取集群的元数据(节点列表和槽位分配信息),并内置一致性哈希逻辑。客户端在执行命令时,会根据命令涉及的键计算哈希值,确定相应的哈希槽,并直接连接到负责该槽位的节点进行操作。这样,客户端能够透明地处理节点间的路由,无需应用程序显式处理节点分配。
Redis 中的一致性哈希主要体现在 Redis Cluster 架构中,通过将数据键和节点映射到同一个哈希环上,并结合哈希槽和虚拟节点技术,实现了数据在节点间的均衡分布和高效路由。这种设计使得 Redis 集群在面对节点动态增删时,能够最小化数据迁移,保持服务的高可用性和数据的高一致性。客户端通过内置一致性哈希逻辑,能够自动寻址并直接与正确节点交互,简化了应用程序的开发和维护。
实现原理就是一致性 Hash。Redis Cluster 中有一个 16384 长度的槽的概念,他们的编号为 0、1、2、3 …… 16382、16383。这个槽是一个虚拟的槽,并不是真正存在的。正常工作的时候,Redis Cluster 中的每个 Master 节点都会负责一部分的槽,当有某个 key 被映射到某个 Master 负责的槽,那么这个 Master 负责为这个 key 提供服务。
至于哪个 Master 节点负责哪个槽,这是可以由用户指定的,也可以在初始化的时候自动生成(redis-trib.rb脚本)。这里值得一提的是,在 Redis Cluster 中,只有 Master 才拥有槽的所有权,如果是某个 Master 的 slave,这个slave只负责槽的使用,但是没有所有权。
Redis Cluster 的分片机制基于哈希槽的概念,通过将键映射到特定的槽位,并将槽位分配给不同的节点,实现了数据在集群内的均匀分布和高效路由。
Redis 集群中的数据是分片存储的,那我们该如何知道某个 key 存在哪个节点上呢?即我们需要一个查询路由,该路由根据给定的 key,返回存储该键值的机器地址。
Redis 的每个节点中都存储着整个集群的状态,集群状态中一个重要的信息就是每个桶的负责节点。在具体的实现中,Redis 用一个大小固定为 CLUSTER_SLOTS 的 clusterNode 数组 slots 来保存每个桶的负责节点。
在集群模式下,Redis 接收任何键相关命令时首先计算键对应的桶编号,再根据桶找出所对应的节点,如果节点是自身,则处理键命令;否则回复 MOVED 重定向错误,通知客户端请求正确的节点,这个过程称为 MOVED 重定向。重定向信息包含了键所对应的桶以及负责该桶的节点地址,根据这些信息客户端就可以向正确的节点发起请求。
至于这个消息体有多大?显然最占空间的就是 myslots 数组:16384÷8÷1024=2kb。如果槽位达到 65536,则所占空间提升到 65536÷8÷1024=8kb,极大浪费带宽。
在预期的集群规模下(通常不超过几千个节点),16384 个槽位可以确保每个节点负责的槽位数量适中,从而实现数据在节点间的相对均匀分布。即使在节点数量较小(如几十个)的情况下,每个节点也能平均分配到数百至数千个槽位,有利于保持数据分布的均衡。
Redis Cluster 的设计者可能参考了其他分布式系统的实践经验,16384 作为常用的一致性哈希槽位数量,已经在其他系统中得到了验证,具有较好的实践效果和社区共识。
PING 消息,以检查它们是否在线。如果一个节点在一定时间内(默认超时时间通常是几百毫秒)没有收到另一个节点的响应,它会标记该节点为 主观下线(Subjectively Down, PFail)。这只是单个节点对另一个节点状态的局部判断。Gossip 协议传播:主观下线状态通过集群内部的 Gossip 协议迅速传播给其他节点。当半数以上的节点(包括自身)都认为某个节点 PFail 时,该节点被宣布为 客观下线(Objectively Down, Fail)。这是整个集群对节点状态达成的共识。
故障确认:为了防止短暂网络波动导致的误判,客观下线通常还伴随着额外的确认步骤,比如多次探测失败、等待一段时间等条件。
一旦一个主节点被标记为客观下线,集群会触发故障迁移过程以恢复服务的高可用性。故障迁移通常包括以下几个步骤:
候选资格:从主节点的从节点(如果有)中选择一个作为新的主节点候选人。通常会选择复制偏移量(replication offset)最高、数据最接近最新的从节点,以减少数据丢失和不一致的风险。
选举触发:选举可以由集群中的其他节点(如哨兵节点,如果部署了哨兵模式)或从节点自己(某些情况下)发起。选举过程可能涉及投票或其他协调机制,以确定哪个从节点应晋升为主节点。
晋升为主节点:被选中的从节点执行 slaveof no one 命令,断开与原主节点的复制关系,将自己的角色提升为新的主节点。
数据接管:由于从节点一直在与原主节点保持同步,因此晋升为主节点后,它已经拥有大部分(如果不是全部)最近的数据。此时,客户端开始向新主节点发送请求。
通知客户端:新主节点通过发送 MOVED 响应告知客户端其新的位置。客户端收到后,更新其内部的槽位映射表,将后续对该槽位的请求直接发送到新主节点。
数据迁移:对于原主节点在下线前未同步给新主节点的少量新写入数据,可能需要通过异步复制或客户端重试等方式进行恢复。同时,其他从节点也会开始与新主节点建立复制关系,以保持数据一致性。
角色调整:当原主节点恢复在线时,它会发现自己不再是主节点,而是变成了从节点。它会自动与新主节点建立复制关系,开始同步数据。
槽位重分配:在某些情况下,原主节点可能需要重新获得部分或全部槽位的分配权,这通常需要手动干预或集群管理工具的支持。
总的来说,Redis Cluster 的故障发现与迁移机制旨在快速检测并响应节点故障,通过自动或半自动的方式将服务从故障节点转移至健康的节点,确保数据的高可用性和服务的连续性。在整个过程中,集群内部通过 gossip 协议、心跳检测和角色转换等手段维持数据的一致性和服务的稳定性。