Redis集群模式详解

Redis有三种主要的集群模式,用于在分布式环境中实现高可用性和数据复制。这些集群模式分别是:主从复制(Master-Slave Replication)、哨兵模式(Sentinel)和Redis Cluster模式。

主从模式

主从模式的简单介绍:包括一个主节点(Master)和一个或多个从节点(Slave)。主节点负责处理所有写操作和读操作,而从节点则复制主节点的数据,并且只能处理读操作。当主节点发生故障时,可以将一个从节点升级为主节点,实现故障转移(但是需要手动实现)。

  • 优点:主从复制的优势在于简单易用,适用于读多写少的场景,解决了单点故障的问题。它提供了数据备份功能,并且可以有很好的扩展性,只要增加更多的从节点,就能让整个集群的读的能力不断提升。

  • 缺点:但是主从模式最大的缺点,就是不具备故障自动转移的能力,没有办法做容错和恢复。主节点和从节点的宕机都会导致客户端部分读写请求失败,需要人工介入让节点恢复或者手动切换一台从节点服务器变成主节点服务器才可以。并且在主节点宕机时,如果数据没有及时复制到从节点,也会导致数据不一致。

主从复制的实现原理

复制的建立过程

  1. 从节点向主节点发送 SYNC 命令:当从节点启动并连接到主节点后,会向主节点发送 SYNC 命令,请求进行数据同步。
  2. 主节点执行 BGSAVE 生成 RDB 文件:主节点收到 SYNC 命令后,会执行 BGSAVE 命令在后台生成一个 RDB(Redis Database)文件,这个文件包含了主节点上的所有数据。同时,主节点会将从节点的连接放入一个队列中,等待 RDB 文件生成完成。
  3. 主节点将 RDB 文件发送给从节点:RDB 文件生成完成后,主节点会将该文件发送给从节点。从节点收到 RDB 文件后,会先将本地数据清空,然后按照 RDB 文件中的数据进行恢复,将数据加载到内存中。
  4. 主节点将缓冲区的写命令发送给从节点:在发送 RDB 文件的同时,主节点会继续处理客户端的写请求,并将这些写命令缓存在一个缓冲区中。当 RDB 文件发送完成后,主节点会将缓冲区中的写命令依次发送给从节点,从节点按照顺序执行这些命令,以保证与主节点的数据一致性。

数据同步后的持续复制过程

  • 命令传播:主节点在处理客户端的写请求时,会将写命令发送给从节点。从节点接收并执行这些命令,从而保持与主节点的数据同步。例如,当主节点执行了一个 SET key value 的命令,它会将这个命令发送给从节点,从节点也会执行同样的命令,将 key 的值设置为 value
  • 心跳检测:从节点会定期向主节点发送心跳包,以告知主节点自己仍然存活并且正常工作。主节点也会通过心跳包来了解从节点的状态,如果主节点长时间没有收到某个从节点的心跳包,就会认为该从节点出现了故障,并进行相应的处理。

部分复制

  • 在 Redis 2.8 版本之后,引入了部分复制的功能,以优化主从复制过程中的数据同步。当主从节点之间的连接出现短暂中断后,重新连接时如果条件允许,主节点只会将中断期间丢失的写命令发送给从节点,而不是像以前那样重新进行全量同步。
  • 这是通过主节点和从节点维护的复制偏移量(replication offset)和复制积压缓冲区(replication backlog buffer)来实现的。主节点会在复制积压缓冲区中记录最近执行的写命令,从节点会记录自己已经接收并执行的写命令的偏移量。当连接恢复时,从节点会将自己的偏移量发送给主节点,主节点根据偏移量判断哪些命令需要发送给从节点,从而实现部分复制。

哨兵模式

为了解决主从模式的无法自动容错及恢复的问题,Redis引入了一种哨兵模式的集群架构。哨兵模式是在主从复制的基础上加入了哨兵节点。哨兵节点是一种特殊的Redis节点,用于监控主节点和从节点的状态。当主节点发生故障时,哨兵节点可以自动进行故障转移,选择一个合适的从节点升级为主节点,并通知其他从节点和应用程序进行更新。通常需要部署多个哨兵节点,以确保故障转移的可靠性。

节点状态监测

  • 定期发送 PING 命令:每个哨兵节点会以一定的时间间隔(可配置)向所有被监控的 Redis 主节点和从节点发送 PING 命令,就像定时给节点 “打招呼”,询问它们是否正常运行。
  • 依据响应判断状态:根据节点对 PING 命令的响应来判断节点的状态。如果节点能在规定时间内回复,说明节点正常运行;如果超过一定时间没有收到响应,哨兵就会认为该节点可能出现了问题。

故障判定

  • 主观下线(SDOWN):当一个哨兵节点在超过 down-after-milliseconds 配置的时间内,没有收到某个主节点的有效响应(例如,主节点没有回复 PING 命令),这个哨兵节点会将该主节点标记为 “主观下线”。这只是单个哨兵节点对主节点状态的初步判断,并不意味着主节点真的无法提供服务了。
  • 客观下线(ODOWN):当多个哨兵节点都认为同一个主节点 “主观下线” 时,它们会进行信息交换和投票。如果达到一定数量(超过配置的 quorum 值)的哨兵节点都同意主节点 “主观下线”,那么这个主节点就会被标记为 “客观下线”,即认为主节点确实发生了故障,需要进行故障转移。

选举过程

哨兵模式涉及两种选举,一种是哨兵领导者的选举,一种是新主节点的选举。

哨兵领导者选举

  • 触发选举:当一个主节点被标记为客观下线时,哨兵们需要选举出一个领导者来执行故障转移流程。
  • 选举过程
    • 每个发现主节点客观下线的哨兵会向其他哨兵发送命令,要求对方选举自己为领导者。
    • 哨兵在收到选举请求后,会根据一定的规则进行投票。例如,每个哨兵只会在一轮选举中给第一个向它请求的哨兵投票。
    • 当一个哨兵获得了超过半数(大于等于 quorum 值)的选票时,它就会被选举为领导者。
    • 如果在一段时间内没有哨兵获得足够的选票,或者出现多个哨兵票数相同的情况,选举过程会重新进行。

新主节点选举

  • 候选从节点筛选:哨兵会根据从节点的一些信息来筛选出合格的候选从节点,通常会考虑以下因素:
    • 从节点与主节点的连接状态,只有处于连接正常且复制状态良好的从节点才会被考虑。
    • 从节点的复制偏移量,复制偏移量越大,说明该从节点的数据越接近主节点,越有可能被选中。
    • 从节点的优先级,通过配置文件可以为不同的从节点设置不同的优先级,优先级高的从节点会优先被考虑。
  • 选举过程
    • 哨兵会对筛选出的候选从节点按照优先级、复制偏移量等因素进行排序。
    • 排在最前面的从节点会被选为新的主节点。如果有多个从节点具有相同的最高优先级和复制偏移量,那么节点 ID 较小的从节点会被选中。
关于复制偏移量(Replication Offset):表示从节点复制主节点数据的进度。

哨兵节点通过发布订阅功能来通知客户端有关主节点状态变化的消息。客户端收到消息后,会更新配置,将新的主节点信息应用于连接池,从而使客户端可以继续与新的主节点进行交互。这个哨兵模式的优点就是为整个集群提供了一种故障转移和恢复的能力。

Cluster集群模式

Redis Cluster是Redis中推荐的分布式集群解决方案。它将数据自动分片到多个节点上,每个节点负责一部分数据。

Redis Cluster采用主从复制模式来提高可用性。每个分片都有一个主节点和多个从节点。主节点负责处理写操作,而从节点负责复制主节点的数据并处理读请求。

Redis Cluster能够自动检测节点的故障。当一个主节点失去连接或不可达时,Redis Cluster会尝试将该节点标记为不可用,并从可用的从节点中提升一个新的主节点。

Redis Cluster是适用于大规模应用的解决方案,它提供了更好的横向扩展和容错能力。它自动管理数据分片和故障转移,减少了运维的负担。

Cluster模式的特点是数据分片存储在不同的节点上,每个节点都可以单独对外提供读写服务。不存在单点故障的问题。

自动分片

Redis数据分片的实现方式通常是将数据按照某种规则(例如,key的hash值)分配到不同的节点上。当客户端想要访问某个key时,它会先计算出这个key应该存储在哪个节点上,然后直接连接到该节点进行操作。因此,对于客户端而言,Redis集群就像是一个大型的、统一的数据库,而不需要关心数据的实际分布情况。

在Redis的Cluster 集群模式中,使用哈希槽(hash slot)的方式来进行数据分片,将整个数据集划分为多个槽,每个槽分配给一个节点。客户端访问数据时,先计算出数据对应的槽,然后直接连接到该槽所在的节点进行操作。Redis Cluster还提供了自动故障转移、数据迁移和扩缩容等功能,能够比较方便地管理一个大规模的Redis集群。

Redis Cluster将整个数据集划分为16384个槽,每个槽都有一个编号(0~16383),集群的每个节点可以负责多个hash槽,客户端访问数据时,先根据key计算出对应的槽编号,然后根据槽编号找到负责该槽的节点,向该节点发送请求。

在 Redis 的每一个节点上,都有这么两个东西,一个是槽(slot),它的的取值范围是:0-16383。还有一个就是 cluster,可以理解为是一个集群管理的插件。当我们的存取的 Key 的时候,Redis 会根据 CRC16 算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。

16384这个数字是一个2的14次方(2^14),尽管crc16能得到2^16 -1=65535个值,但是并没有选择,主要从消息大小和集群规模等方面考虑的:

  • 正常的心跳数据包携带了节点的完整配置,在更新配置的时候,可以以幂等方式进行替换。这意味着它们包含了节点的原始槽配置,对于包含16384个槽位的情况,使用2k的空间就够了,但如果使用65535个槽位,则需要使用8k的空间,这就有点浪费了。

  • 由于其他设计权衡的原因,Redis Cluster不太可能扩展到超过1000个主节点,这种情况下,用65535的话会让每个节点上面的slot太多了,会导致节点的负载重并且数据迁移成本也比较高。而16384是相对比较好的选择,可以在1000个节点下使得slot均匀分布,每个分片平均分到的slot不至于太小。

    CRC16(Cyclic Redundancy Check,循环冗余校验码)算法是一种广泛使用的校验算法,主要用于数据通信和数据存储等领域,例如网络通信中的错误检测和校正、数据存储中的文件校验和等。 当我们的存取的 Key 的时候,Redis 会根据 CRC16 算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽。CRC16算法基于多项式除法,将输入数据按位进行多项式除法运算,最后得到一个16位的校验码。

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部