Redis-集群

Redis主从同步机制详解

完全同步

在Redis的主从复制(Replication)机制中,完全同步(Full Synchronization)是一个关键过程,它确保从节点(Replica)能够获取主节点(Master)的完整数据集。完全同步通常发生在以下几种情况:

  1. 初次同步:当一个从节点首次连接到主节点时,它需要获取主节点的完整数据集。这是因为在初次连接时,从节点没有任何数据,因此需要进行一次完全同步。

  2. 从节点数据丢失:如果从节点由于系统崩溃、故障断电等原因导致数据丢失,它将无法继续提供服务。此时,从节点会向主节点发起完全同步请求,以恢复数据。

  3. 数据差异过大:在某些情况下,从节点可能长时间未与主节点进行同步,导致两者之间的数据差异过大。当差异超出预设的阈值时,从节点会主动发起完全同步请求,以确保数据的一致性。

完全同步的三阶段

主从服务器之间的完全同步过程可以分为三个主要阶段:

  1. 建立连接与协商同步:主节点和从节点之间首先建立网络连接。从节点发送PSYNC命令(在Redis 2.8及以上版本中使用),请求与主节点进行同步。主节点响应FULLRESYNC命令,表示将进行完全同步,并提供一个唯一的同步ID(Replication ID)和当前的偏移量(Offset)。

  2. 主节点发送完全同步数据:主节点接收到从节点的同步请求后,会生成一个RDB快照文件。这个快照文件包含了主节点当前的所有数据。主节点将生成的RDB文件发送给从节点。

  3. 主节点发送新写命令:在RDB文件生成和传输期间,主节点会将所有新的写操作命令记录到一个称为replication backlog buffer的缓冲区中。当RDB文件传输完成后,主节点会将replication backlog buffer中的所有写操作命令发送给从节点。从节点接收到这些命令后,会依次执行这些命令,从而与主节点的数据保持一致。

实现过程详解

这里参考一张小林哥的图:Redis主从同步(完全同步)

  1. 主节点发送SYNC命令:在Redis 2.8之前的版本中,主节点会发送SYNC命令来启动同步过程。而在Redis 2.8及以上版本中,主节点会发送PSYNC命令,该命令支持部分重同步(Partial Resynchronization),但在初次同步时,仍然会执行完全同步。

  2. 生成RDB文件:主节点接收到从节点的同步请求后,会调用BGSAVE命令生成一个RDB快照文件。这个过程是异步的,主节点会在后台生成快照,同时继续处理客户端的请求。RDB文件生成完成后,主节点会将文件发送给从节点。

  3. 传输RDB文件:主节点通过网络将生成的RDB文件传输给从节点。传输过程中,主节点会继续记录新的写操作命令到replication backlog buffer中。从节点接收到RDB文件后,会将其加载到内存中,并应用其中的数据。

  4. 主节点记录写操作:在RDB文件生成和传输期间,主节点会将所有新的写操作命令记录到replication backlog buffer中。这个缓冲区的大小是有限的,通常为1MB,因此在高写入负载下,缓冲区可能会被填满。

  5. 传输新写命令:当RDB文件传输完成后,主节点会将replication backlog buffer中的所有写操作命令发送给从节点。从节点接收到这些命令后,会依次执行这些命令,从而与主节点的数据保持一致。

增量同步

在Redis的主从复制机制中,增量同步(Partial Resynchronization)是一种高效的同步方式,它允许从节点(Replica)在网络恢复后,仅同步自上次同步以来主节点(Master)新增的数据,而不需要进行完整的完全同步(Full Synchronization)。增量同步基于PSYNC命令,并依赖于运行ID(run ID)和复制偏移量(offset)来实现。

增量同步的步骤

还是借用小林哥的图:

Redis主从同步-增量同步

增量同步的过程主要包括以下三个步骤:

  1. 从节点恢复网络并发送PSYNC命令:当从节点恢复网络连接后,它会向主节点发送PSYNC命令,请求进行增量同步。此时,PSYNC命令中的offset参数不再是-1,而是从节点上次同步时的复制偏移量。

  2. 主节点响应CONTINUE命令:主节点接收到从节点的PSYNC命令后,会检查从节点提供的复制偏移量是否在repl_backlog_buffer缓冲区中。如果存在,主节点会响应CONTINUE命令,表示接下来将进行增量同步。

  3. 主节点发送增量数据:主节点将从节点断线期间收到的所有写操作命令发送给从节点。从节点接收到这些命令后,会依次执行这些命令,从而与主节点的数据保持一致。

增量数据的来源

主节点如何知道从节点缺少的是哪些增量数据呢?这主要依赖于两个关键组件:

  • repl_backlog_buffer缓冲区:这是一个环形缓冲区,用于存储主节点近期传播的写操作命令。当从节点断连后,主节点可以通过这个缓冲区找到从节点缺失的数据。
  • **replication offset**:这是一个标记,用于记录主从节点各自的同步进度。主节点使用master_repl_offset来记录自己写到的位置,从节点使用slave_repl_offset来记录自己读到的位置。

repl_backlog_buffer缓冲区的写入时机

在主节点传播命令时,它会将写操作命令发送给从节点的同时,也会将这些命令写入到repl_backlog_buffer缓冲区中。因此,repl_backlog_buffer缓冲区中存放了近期传播的写操作命令。

增量同步的判断条件

当从节点断连后重新发起同步请求时,它会将自己的slave_repl_offset发送给主节点。主节点会根据master_repl_offset比较二者之间的数据差距,并判断是否可以进行增量同步。具体判断条件如下:

  1. 增量同步:如果从节点索要读取的数据还在repl_backlog_buffer缓冲区中(即主从节点的偏移量之差没有超过缓冲区的长度,可以抽象为没有被“套圈”),则采用增量同步方式。
  2. 完全同步:如果从节点索要的数据已经不在repl_backlog_buffer缓冲区中,说明落后数据太大,中间已有写操作缺失。为保证数据一致性,需要进行完全同步。

repl_backlog_buffer缓冲区的大小与调整

repl_backlog_buffer缓冲区的默认大小是1MB,并且由于它是一个环形缓冲区,当缓冲区写满后,主节点继续写入的话,就会覆盖之前的数据。因此,当主节点的写入速度远超于从节点的读取速度时,缓冲区的数据很快就会被覆盖。

为了避免在网络恢复时频繁地使用完全同步的方式,我们应该调整repl_backlog_buffer缓冲区的大小,尽可能地大一些,以减少从节点要读取的数据被覆盖的概率,从而使得主节点能够更多地采用增量同步的方式。

扩展:Redis集群和主从同步能保证数据一致性吗?

在分布式系统中,数据一致性是一个关键问题。Redis作为一个高性能的内存数据库,其主从复制和集群模式在设计上遵循了CAP理论中的AP模型,即保证高可用性(Availability)和分区容错性(Partition Tolerance),而牺牲了强一致性(Consistency)。也就是说,在网络分区的情况下,Redis能够保证服务的可用性,但可能会出现部分节点间数据不一致的情况。

Redis 哨兵机制原理

在Redis的主从架构中,主节点(Master)负责处理所有的写操作,而从节点(Replica)则负责处理读操作。这种读写分离的架构在大多数情况下能够提供良好的性能和扩展性。然而,当主节点发生故障时,整个系统将无法处理写请求,从而导致服务中断。为了解决这个问题,Redis在2.8版本之后引入了哨兵机制(Sentinel),用于实现主从节点的故障转移。

哨兵机制的作用

哨兵机制的主要作用是实现主从节点的故障转移,确保在主节点发生故障时,系统能够自动选举出一个新的主节点,并通知其他从节点和客户端更新配置,从而保证服务的连续性和高可用性。

哨兵节点的角色

哨兵节点是一个运行在特殊状态下的Redis进程,它充当观察者的角色,主要负责监控主从节点的状态。哨兵节点通过以下三个主要动作来实现故障转移:

  1. 观察(Monitoring)

    • 哨兵节点会定期向主节点和从节点发送心跳检测(PING)命令,以确认它们的状态。
    • 如果主节点在一定时间内没有响应,哨兵节点会认为主节点发生了故障。
  2. 选举(Election)

    • 当哨兵节点检测到主节点故障时,它会与其他哨兵节点进行协商,选举出一个新的主节点。
    • 选举过程遵循Raft算法或类似的分布式一致性算法,确保选举结果的一致性和可靠性。
  3. 通知(Notification)

    • 一旦新的主节点被选举出来,哨兵节点会通知其他从节点更新配置,指向新的主节点。
    • 同时,哨兵节点还会通知客户端新的主节点的信息,以便客户端能够继续发送写请求。

哨兵机制算法流程

当Redis集群的主节点发生故障时,Sentinel机制将启动故障转移流程,从剩余的从节点中选举出一个新的主节点。这个过程主要分为四个步骤:故障节点主观下线、故障节点客观下线、Sentinel集群选举Leader、Sentinel Leader决定新主节点。

故障节点主观下线

Sentinel集群中的每一个Sentinel节点会定时对Redis节点发送心跳检测包(PING),以检测节点是否正常运行。如果在down-after-milliseconds时间内,Redis节点没有回复Sentinel节点的心跳包,该Sentinel节点就会认为该节点主观下线(Subjectively Down, SDOWN)。

故障节点主观下线

故障节点客观下线

当一个Sentinel节点认为某个Redis节点主观下线时,它无法单独证明该节点确实下线了。因此,Sentinel节点会询问其他Sentinel节点,共同判断该节点是否客观下线(Objectively Down, ODOWN)。

如果Sentinel集群中超过quorum数量的节点认为该Redis节点下线了,则该Redis节点客观下线。

客观下线

若客观下线的是从节点,则检测到此结束,不会进行下一步了;若该节点是主节点,则需要进行接下来的故障转移。

Sentinel集群选举Leader

在决定新的主节点之前,Sentinel集群需要先选举出一个Sentinel Leader,代表Sentinel集群进行决策。每个Sentinel节点都有机会成为Leader。

每个Sentinel节点够可以变成Leader,在判定主节点主观下线后,节点会向Sentinel其他节点发送请求,将自己选举为Leader。被请求的节点如果没有为其他Sentinel节点投过票,则发起请求的节点票数+1,否则不增加票数。

如果一个Sentinel节点获得的票数达到Leader的最低票数(max(quorum, Sentinel集群节点数/2 + 1)),则该节点变成leader,否则重新选举。

Sentinel Leader决定新主节点

Sentinel集群选举出Leader后,由Leader决定哪个从节点成为新的主节点。选择新主节点的过程遵循以下优先级:

  1. 过滤故障节点:首先,过滤掉已经下线的从节点。
  2. 选择优先级最高的从节点:选择slave-priority值最大的从节点作为新的主节点。如果存在多个从节点具有相同的优先级,则继续下一步。
  3. 选择复制偏移量最大的从节点:选择slave_repl_offset值最大的从节点作为新的主节点。slave_repl_offset表示从节点与主节点的数据同步进度。如果存在多个从节点具有相同的复制偏移量,则继续下一步。
  4. 选择runid最小的从节点:选择runid最小的从节点作为新的主节点。runid是Redis节点的唯一标识符。

Redis 切片集群详解

随着数据量的增长,单个 Redis 节点的存储容量和性能可能无法满足需求。为了解决这一问题,Redis 提供了切片集群(Redis Cluster)方案。通过将数据分布在多个服务器上,Redis Cluster 不仅降低了单点故障的风险,还显著提升了读写性能。本文将深入探讨 Redis Cluster 的工作原理、优点和缺点,并通过实例帮助读者更好地理解。

Redis Cluster 的工作原理

哈希槽(Hash Slots)

Redis Cluster 采用哈希槽的方式来管理数据和节点之间的映射关系。一个 Redis Cluster 包含 16384 个哈希槽,这些哈希槽类似于数据分区。每个键值对(key-value pair)都会根据其 key 映射到一个特定的哈希槽中。具体步骤如下:

  1. CRC16 哈希算法:首先,Redis 使用 CRC16 算法对键值对的 key 进行计算,得到一个 16 位的值。
  2. 哈希槽映射:然后,将这个 16 位的值对 16384 取模,得到一个 0 到 16383 之间的余数。这个余数即为该键值对对应的哈希槽编号。

哈希槽与节点的映射

在 Redis Cluster 中,哈希槽需要映射到具体的 Redis 节点上。有两种常见的映射方式:

  • 平均分配:当使用 cluster create 命令创建集群时,Redis 会自动将 16384 个哈希槽平均分配到各个节点中。例如,如果集群中有 5 个节点,每个节点将分配到 16384 / 5 ≈ 3276 个哈希槽。

  • 手动分配:在某些情况下,可能需要手动分配哈希槽。可以通过 cluster meet 命令手动建立节点之间的连接,然后使用 cluster addslots 命令为每个节点分配指定的哈希槽数量。例如,可以手动将哈希槽 0 到 5000 分配给节点 A,将 5001 到 10000 分配给节点 B,以此类推。

Redis Cluster 的优缺点

优点

1. 高可用性:Redis Cluster 通过主从复制(Master-Slave Replication)机制实现了高可用性。每个节点都可以配置一个或多个从节点,主节点负责处理写请求,从节点负责处理读请求。当主节点发生故障时,从节点可以自动接管主节点的角色,确保服务的连续性。

2. 高性能:Redis Cluster 采用数据分片机制,将数据分散到多个节点上,从而降低了单个节点的负载压力。这种分布式架构显著提升了系统的读写性能和吞吐量。

3. 高扩展性:Redis Cluster 支持动态扩展,可以根据需求增加或减少节点。此外,集群模式还可以将某些节点设置为代理节点(Proxy Nodes),自动转发请求,增加了系统的灵活性和可定制性。

缺点

1. 部署和同步复杂:Redis Cluster 的部署和维护相对复杂。特别是在大规模集群中,节点之间的同步和数据一致性管理需要特别注意。

2.集群同步问题:在 Redis Cluster 中,节点之间的数据同步是一个关键问题。如果同步不及时或出现错误,可能会导致数据丢失或不一致。

3.数据分片限制:虽然 Redis Cluster 通过数据分片提升了性能,但在某些情况下,数据分片可能会带来一些限制。例如,某些复杂的查询操作可能需要跨多个节点进行,增加了系统的复杂性。