自学内容网 自学内容网

Redis数据库笔记——Cluster集群模式

大家好,这里是Good Note,关注 公主号:Goodnote,专栏文章私信限时Free。本文详细介绍Redis数据库的Cluster集群模式,包括工作原理,哈希槽,路由和配置原理等。

在这里插入图片描述

什么是 Redis Cluster 集群?

Redis Cluster 在 3.0 版本中引入,是 Redis 的集群模式解决方案。提供了一种原生的分布式集群解决方案,用于解决 Redis 的水平扩展(sharding)问题【类似MySQL的分库分表】,自动将数据划分为多个分片(Shards),每个分片由一个主节点(Master)负责。每个主节点可以有多个从节点(Slave)用于数据冗余备份。

Redis Cluster 由多个节点组成,节点之间通过内部通信协议进行数据交换和协作。Redis Cluster 采用分布式哈希(hashing) 方式来管理数据,通过将数据分片并分配给不同的节点,确保每个 Redis 节点只管理一部分数据。整个集群由多个 Redis 实例(包括主节点和从节点)组成,数据在集群中的多个节点之间分布。

在这里插入图片描述

上图假设有三个主节点,Redis Cluster 的关键部件包括:

  • 分片(Sharding):Redis Cluster 将整个数据集划分为 16384 个槽,每个槽可以存储一个键值对。每个节点负责一部分槽,并根据哈希算法决定每个键的槽。
  • 主从节点:每个分片有一个主节点和多个从节点。从节点用于数据备份和故障转移。
    • 主节点(Master Node):负责处理数据存储、命令请求、读写操作,并将数据分配到对应的槽
    • 从节点(Replica Node):从主节点同步数据并提供只读服务,主节点宕机时自动提升为新的主节点。

为什么需要 Redis Cluster 集群?

  1. 水平扩展(Sharding)
    Redis 是一个高性能的单机内存数据库,单机模式下,由于内存和 CPU 的限制,数据量和并发处理能力会受到限制。Redis Cluster 通过数据分片(sharding)技术,将数据分散到多个节点上,从而实现水平扩展(scale-out)。这种方式可以大大提高 Redis 的存储容量和处理能力

  2. 容错能力及高可用性【类似哨兵机制】
    在传统的 Redis 主从复制架构中,如果主节点故障,需要手动恢复或切换到备份节点,这样会导致系统停机。Redis Cluster 通过自动故障转移机制来提高系统的高可用性。在 Redis Cluster 中,如果某个主节点故障,集群会自动将某个从节点提升为新的主节点,保证数据的持续可用。

  3. 负载均衡【类似主从复制】
    Redis Cluster 可以自动将数据分布到多个节点上,不同的节点处理不同的请求,这样可以均衡地分担负载,避免某个节点成为瓶颈。客户端请求会根据数据的哈希值路由到正确的节点,从而分摊了处理压力。

  4. 减少单点故障(SPOF)
    在没有 Redis Cluster 的情况下,如果某个 Redis 实例发生故障,整个系统会变得不可用,导致单点故障(SPOF)。Redis Cluster 通过将数据分片并在多个节点间分配,避免了单点故障的发生,从而提高了集群的可用性和可靠性。

Redis Cluster 的工作原理

数据分片(Sharding)
  • Redis Cluster 使用一致性哈希算法将数据划分为 16384 个槽,每个槽负责一个数据范围。
  • 通过 hash slot 算法,Redis 会根据键的哈希值将其映射到一个特定的槽。例如,key1 被映射到槽 1024,key2 被映射到槽 2048。
  • Redis Cluster 会将这些槽分配到集群中的主节点上。每个主节点负责一个或多个槽。
数据路由
  • 当客户端发起请求时,Redis Cluster 会根据键的哈希值确定请求的目标节点。客户端会通过 槽映射 来确定请求的主节点地址。
  • 如果客户端请求的数据不在当前节点上,节点会返回一个 MOVED 错误,告知客户端数据所在的实际节点地址。客户端会根据该信息重新发送请求。
故障转移【类似哨兵机制】
  • Redis Cluster 提供了内置的故障转移机制。每个主节点有一个或多个从节点用于备份数据。
  • 当一个主节点宕机时,Redis Cluster 会自动选举一个从节点来替代它。这是通过 投票机制 完成的,通常选择最新同步的从节点。
  • 故障转移是透明的,客户端无感知,确保系统高可用。
扩容和缩容
  • Redis Cluster 支持动态扩展和缩减节点。通过 reshard 操作,可以将槽从一个节点移动到另一个节点,从而平衡负载或增加集群容量。
  • 扩容时,可以通过 增加节点 来将槽分配到新的节点上。缩容时,可以通过将槽迁移到其他节点来减少节点数量。

哈希槽数据分片

普通哈希(Hashing)

普通哈希(或传统的分片机制)是一种简单的方式,它通过计算某个键(key)的哈希值,将其映射到特定的服务器或节点上。典型的实现方式是通过对哈希值求模,确定数据存储的节点。

这种方法简单且易于实现,但当集群规模发生变化(比如增加或移除节点)时,存在几个显著的问题:

  1. 数据迁移问题
    • 节点增加时:普通哈希算法在节点增加时,通常需要重新计算现有数据的哈希值,并根据新的节点数重新分配数据。这会导致大量的数据需要被重新分配和迁移,造成很大的性能开销,尤其是在大规模的系统中。
    • 节点减少时:同样,如果移除一个节点,所有由该节点负责的数据也需要被重新分配到剩余节点,这个过程可能同样导致大量的数据迁移。
  2. 扩展性差
    • 由于每次增加或减少节点时,数据的重新分配会非常繁琐且开销巨大,这使得使用普通哈希在动态扩展集群时显得不够高效和灵活。
  3. 负载不均衡
    • 在节点数较少的情况下,普通哈希可能导致负载不均,某些节点可能存储了大量的数据,而其他节点存储的数据较少。当节点数发生变化时,负载均衡的调整并不灵活。

解决这些问题的方法是使用一致性哈希。

一致性哈希

一致性哈希 是一种解决分布式系统中数据分配和负载均衡问题的算法,尤其适用于节点动态变化的情况(例如,增加或减少节点)。它的核心思想是将节点和数据映射到一个虚拟的环形空间中,而不是简单地通过哈希值对节点数取模。

一致性哈希的基本概念:

  1. 哈希环:一致性哈希将数据和节点映射到一个哈希环上,哈希环上的位置由哈希函数决定。每个节点和数据都会计算一个哈希值,然后被放置到环的某个位置上。

  2. 数据分配:数据会根据哈希值顺时针找到第一个节点进行存储。如果某个节点失效,数据会转到顺时针方向的下一个节点,从而确保数据的高可用性。

  3. 节点变化:当增加或删除节点时,一致性哈希只需要迁移哈希环上一小部分的数据,而不是全部数据,极大减少了数据迁移的量。

一致性哈希的优势:

  1. 减少数据迁移

    • 一致性哈希的最大优势是,在节点增加或减少时,只有一部分数据会被迁移。即使增加了新的节点,只有一小部分数据会从其他节点迁移到新节点,而绝大部分数据保持不变。
    • 这是因为一致性哈希利用了虚拟节点的概念,将多个虚拟节点映射到哈希环上,这样每个实际节点只会占据环上的某一小段范围。
  2. 更好的负载均衡

    • 一致性哈希通过虚拟节点的方式,使得每个物理节点在哈希环上分布得更加均匀,从而实现更好的负载均衡。每个节点负责多个虚拟节点,减少了负载不均的情况。
  3. 扩展性

    • 一致性哈希允许动态扩展集群。当需要增加节点时,只需为新节点分配适当数量的虚拟节点,其他节点的数据分布几乎不受影响。节点移除时,只需要将该节点的数据重新分配给相邻的节点。

但是,一致性哈希也存在一些局限性:

  1. 虚拟节点的管理的复杂性

    • 一致性哈希引入了虚拟节点的概念。虽然虚拟节点能带来更均匀的负载,但也增加了系统的复杂性。虚拟节点的数量需要根据负载情况灵活调整,而这在实现上可能会增加一定的管理和计算成本
  2. 节点之间的负载差异

    • 虽然虚拟节点能在一定程度上减少负载不均衡的情况,但一致性哈希本身并不保证绝对均衡。如果哈希环上的虚拟节点分布不均,仍然可能存在某些节点负载过重的情况。
  3. 迁移逻辑复杂

    • 节点增加或移除时,数据需要根据一致性哈希算法重新分配,这虽然减少了迁移量,但依然存在一定的数据迁移,特别是在节点数变化较大的情况下。
Redis 集群使用哈希槽

Redis 集群采用了 哈希槽(Hash Slots)的方式,避免了纯粹依赖一致性哈希的复杂性。Redis 集群将所有的键通过哈希计算分配到 16384固定的槽(slots) 中。每个 Redis 节点负责一定数量的哈希槽。

哈希槽的优势
  1. 简单而有效的扩展机制

    • Redis 集群通过固定数量的哈希槽(16384个)来分配数据。每个节点只负责这些哈希槽中的一部分。这使得节点的增加或移除非常简单。扩展时,只需要将部分哈希槽迁移到新节点,数据迁移量小,且几乎不会影响其他节点的工作。
  2. 自动负载均衡

    • 哈希槽的数量是固定的,因此所有节点的负载能够更加均匀地分配。如果有一个节点加入集群,只需要将部分哈希槽重新分配给它,负载就能均匀地分布到所有节点。
  3. 减少数据迁移

    • 在 Redis 集群中,只有在增加或移除节点时,才需要迁移数据。每个哈希槽都被一个特定节点管理,因此集群的扩展不会造成系统的大规模数据迁移,减少了开销。
  4. 精确的控制

    • 哈希槽为每个节点分配了明确的职责范围,因此 Redis 集群可以在扩展时进行精确的哈希槽迁移。与一致性哈希相比,哈希槽能提供更加明确和稳定的管理方式。
哈希槽的工作原理
  • Redis 集群中的所有键都通过 CRC16 算法计算一个哈希值,然后通过对 16384 取模来映射到某一个哈希槽。每个哈希槽由集群中的一个节点负责。

  • 哈希槽数量固定为 16384,因此 Redis 集群能够确保数据的均匀分布,并且扩展时不会造成过多的数据迁移。

  • 节点增加时,Redis 只需要将部分哈希槽迁移到新节点即可;节点移除时,Redis 会将该节点的哈希槽迁移到其他节点。

为什么RedisCluster会设计成16384个槽【 0 ~ 16383 】呢?

在这里插入图片描述

对于常见的 CRC16 实现(如 CRC-16-ANSICRC-16-IBM),它们使用 16 位的校验和,因此可以有 2^16 = 65536 种不同的余数(哈希值)。为什么 Redis 集群使用 16384 个槽位?

antirez(Redis 的贡献者)在 2015年5月12日 评论道: 原因是:

  1. 正常的心跳包携带节点的完整配置,这些配置可以通过幂等的方式替换旧配置。也就是说,它们包含节点的槽位配置,以原始形式表示,使用 2k 的空间,具有 16k 个槽位,但如果使用 65k 个槽位,将会占用 8k 的空间,代价非常高。
  2. 同时,考虑到 Redis 集群的其他设计权衡,Redis 集群不太可能扩展到超过 1000 个主节点。

因此,16k 是一个合适的范围,确保每个主节点有足够的槽位,同时最大支持 1000
个主节点,但又足够小,可以轻松地将槽位配置表示为原始位图。请注意,在小型集群中,位图很难压缩,因为当节点数 N 较小时,位图中会有
槽位/N 个比特被设置为 1,而这占用了大量的比特位。

  • 槽位数 16384 既能保证带宽和内存的合理利用,又能适应最多 1000 个主节点的设计。
  • 心跳包大小 是选择槽位数的一个重要因素,避免了大规模槽位带来的性能和带宽问题。
  • 位图压缩 在节点数较少时的效率较低,但 16384 个槽位在多数情况下可以实现良好的压缩和性能平衡。

以下是对每个要点的详细解释和确认:

  1. 心跳消息过大
  • 槽位为 65536 时,消息头过大:当槽位数为 65536 时,表示需要一个 65536 ÷ 8 = 8192 字节(8 KB)的位图来表示节点所负责的槽。这会导致心跳消息的大小过大,增加带宽负担,因为 Redis 节点需要频繁发送心跳消息(例如每秒一次)。如果每个消息头都达到 8 KB,对于网络带宽和性能来说,会产生显著的影响。

  • 为什么 16384 是合适的:如果将槽位数减少到 16384(2^14),位图的大小将是 16384 ÷ 8 = 2 KB,这样可以有效减少心跳消息的负担,不会造成不必要的带宽浪费。

每个槽位 1 bit → 每 8 个槽位 1 字节。所以 “÷ 8”。

  1. 集群主节点数量限制
  • 主节点数量限制为 1000:Redis 集群的主节点数量理论上可以更多,但实际设计中,Redis 的作者认为超过 1000 个主节点会导致其他问题,比如网络拥堵和复杂性增加。随着集群中节点数量的增加,心跳消息的传输开销也会增加,因此建议在实际部署中,主节点数量不要超过 1000。

  • 16384 个槽位与节点数量的匹配:在 1000 个主节点以内,16384 个槽位足以满足需求,因为每个主节点平均分配到 16 个槽位。这是一个合理的分配,既保证了每个节点的负载适中,又不会浪费内存或带宽。使用 65536 个槽位会导致每个主节点需要管理更多槽位,甚至可能使某些主节点的负载不均。

  1. 槽位数与位图(Bitmap)压缩
  • 节点数少时,压缩率低:位图的压缩效果与槽位的填充率有关。当集群中的节点数(N)较少时,位图的填充率较高(槽位数 / 节点数),导致大部分位都被设置为 1,这时位图的压缩效率较低。反之,节点数较多时,位图的填充率低,压缩效果更好。

  • 16384 个槽位与压缩率:在一个相对较小的集群中(如少量节点),16384 个槽位使得位图的填充率适中,能够在保证性能的同时有效压缩。比如,假设有 100 个节点,每个节点负责大约 163 个槽位,位图的压缩效率更高,不会浪费太多空间。

总结
  1. 普通哈希 的问题:节点增加或减少时,需要大规模迁移数据,导致性能下降和系统负载不均。
  2. 一致性哈希 的优势:减少数据迁移、提升扩展性,但增加了虚拟节点的管理复杂度,并且在节点数量较多时,可能仍然出现负载不均的情况。
  3. 哈希槽 是 Redis 集群解决数据分片的核心。通过固定数量的哈希槽,Redis 集群能够高效地管理数据分配,简化节点的扩展、负载均衡和故障恢复。

Redis 集群的哈希槽机制在保证扩展性的同时,避免了使用一致性哈希时可能带来的复杂性和性能问题,是一个适应大规模、高并发环境下的高效分布式方案。

数据路由(Data Routing)

在 Redis Cluster 中,数据路由 是指根据客户端请求的 key,将请求路由到存储该数据的正确 Redis 节点的过程。由于 Redis Cluster 使用 哈希槽 来分散数据到不同的节点,因此每个请求都需要通过哈希值确定该数据存储在哪个节点。当客户端请求的 key 不在当前节点的哈希槽范围内时,节点会返回 MOVED 错误,指示客户端应该向目标节点发起请求。客户端能够根据这个信息自动调整,确保数据请求能够成功完成。

其流程如下:

  1. CLUSTER NODES 命令

    • 当客户端连接到 Redis Cluster 时,通常会通过 CLUSTER NODES 命令获取集群节点的信息。通过该命令,客户端可以知道哪些节点负责哪些哈希槽,从而进行适当的路由。
    • 在 Redis Cluster 中,集群中的每个节点都有一个唯一的标识符,并且每个节点会跟踪集群中其他节点的状态和哈希槽分配情况。客户端会根据这些信息来决定如何分配请求。
  2. 哈希槽和键值映射

    • Redis Cluster 中的数据根据 哈希槽(slot)分布在不同的节点上。集群总共有 16,384 个哈希槽(编号从 0 到 16,383)。每个键(key)通过计算其 哈希值 来确定它应该存储在哪个哈希槽内,进而确定它应该存储在哪个节点上。
    • 计算哈希槽的方式是通过 CRC16 校验算法对 key 进行哈希运算,然后通过对 16,384 取模来获得对应的哈希槽。
    slot = CRC16(key) % 16384
    

    每个 Redis 节点(主节点)会负责一定范围的哈希槽。客户端会根据哈希值,自动将请求路由到相应的节点。

  3. 客户端请求处理

    • 客户端在发送请求时,首先会计算 key 的哈希槽值,然后检查当前连接的节点是否负责该哈希槽。如果负责,则该节点会处理该请求并返回结果。
    • 如果客户端请求的 key 不在当前节点负责的哈希槽范围内,当前节点会返回一个 MOVED 错误。这个错误包含目标节点的地址,告诉客户端该请求应该发送到哪个节点。
    • 客户端收到 MOVED 错误后,会根据错误信息自动重新路由请求到目标节点。

    例如:

    • 假设客户端连接的是一个负责哈希槽范围 [0, 5461] 的节点,但客户端请求的数据 key = "foo" 的哈希槽值是 7000,即该数据应该存储在另一个节点上。当前节点会返回一个类似的错误信息:

      MOVED 7000 192.168.1.100:7001
      

      这意味着 key = "foo" 应该存储在 192.168.1.100:7001 节点上。客户端会根据此信息重新连接到目标节点并重新发起请求。

  4. 请求转发

    • 由于客户端的自动路由机制,客户端在收到 MOVED 错误后会根据新的目标节点地址重新发送请求。这样,客户端在发生 MOVED 错误时,能够自我调整,避免集群中节点之间的路由问题,保证数据请求的顺利进行。
  5. 多键操作

    • Redis Cluster 中的多键操作(如 MSETMGET 等)具有一定的限制。为了保证原子性,这些操作要求所有相关的 key 必须位于相同的哈希槽内。也就是说,如果请求的多个 key 的哈希槽不同,操作会失败,客户端会收到 ASK 错误,提示该操作需要路由到不同的节点。

Redis Cluster 配置与管理

配置

每个 Redis 节点都有一个配置文件(redis.conf),通过以下配置来启用集群模式:

  • cluster-enabled yes:启用集群模式。
  • cluster-config-file nodes.conf:指定集群的配置文件存储位置。
  • cluster-node-timeout 15000:指定节点超时的最大时间,超过此时间认为节点不可用。
集群的创建与管理
  • 创建集群:Redis 提供了 redis-cli 工具来创建和管理集群。通过 redis-trib.rbredis-cli --cluster 命令,可以创建和配置 Redis Cluster。

    • 可以通过以下命令启动多个 Redis 实例并组成一个 Redis 集群:

      redis-server --port 7000 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000
      
  • 扩展集群:可以通过 redis-cli --cluster add-node 来扩展集群,添加新节点。

  • 监控集群状态:可以通过 redis-cli --cluster check 命令检查集群的健康状态和分布情况。

  • 集群管理

    • 使用 redis-trib 工具可以方便地管理 Redis 集群,如创建集群、添加节点、删除节点、重分片等。
故障恢复与重分片
  • 故障恢复:如果某个节点宕机,集群会自动进行故障转移,将从节点提升为新的主节点。管理员可以通过监控工具和日志检查故障发生的原因。
  • 重分片:当节点的负载不均时,Redis Cluster 提供了 redis-trib.rb reshard 命令来进行槽的重新分配,平衡节点的存储负载。

Redis Cluster 的优点与缺点

优点
  1. 水平扩展:通过增加节点,Redis Cluster 能够动态扩展容量和处理能力。
  2. 高可用性:通过主从复制和自动故障转移,保证了集群的高可用性。
  3. 负载均衡:自动将数据分片到不同的节点上,避免单个节点的负载过重。
  4. 数据高可用:每个主节点都有从节点备份,主节点宕机时可以自动进行故障转移。
缺点
  1. 复杂性:集群模式的配置和管理相对较为复杂,需要了解节点的配置、分片机制和故障转移机制。
  2. 部分操作限制:一些 Redis 操作(如 MULTI/EXEC 事务)在集群模式下受到限制,跨分片的操作可能会导致性能问题。
  3. 单点故障风险:尽管 Redis Cluster 提供了故障转移,但如果集群的管理节点(如某个重要的主节点)发生故障,可能会导致服务中断。

总结

Redis Cluster 是一个高效、可扩展的分布式解决方案,它通过数据分片、主从复制、故障转移等机制提供了高可用性和可扩展性。它适用于需要处理大量数据和高并发的应用场景,尽管它的配置和管理相对复杂,但在现代分布式系统中,Redis Cluster 提供了非常强大的支持。

历史文章

MySQL数据库

  1. MySQL数据库笔记——数据库三范式
  2. MySQL数据库笔记——存储引擎(InnoDB、MyISAM、MEMORY、ARCHIVE)
  3. MySQL数据库笔记——常见的几种锁分类
  4. MySQL数据库笔记——索引介绍
  5. MySQL数据库笔记——事务介绍
  6. MySQL数据库笔记——索引结构之B+树
  7. MySQL数据库笔记——索引潜规则(回表查询、索引覆盖、索引下推)
  8. MySQL数据库笔记——索引潜规则(最左前缀原则)
  9. MySQL数据库笔记——常见慢查询优化方式
  10. MySQL数据库笔记——日志介绍
  11. MySQL数据库笔记——多版本并发控制MVCC
  12. MySQL数据库笔记——主从复制

Redis

  1. Redis数据库笔记——数据结构类型
  2. Redis数据库——Redis雪崩、穿透、击穿
  3. Redis数据库——内存淘汰机制
  4. Redis数据库笔记——内存分配器
  5. Redis数据库笔记——内存预分配
  6. Redis数据库笔记—— Hash(哈希)的扩容机制(rehash)
  7. Redis数据库笔记——ZSet的底层实现(跳表)
  8. Redis数据库笔记——布隆过滤器(BloomFilter)
  9. Redis数据库笔记——持久化机制
  10. Redis数据库笔记——部署模式
  11. Redis数据库笔记——主从复制
  12. Redis数据库笔记——Sentinel哨兵机制

原文地址:https://blog.csdn.net/haopingbiji/article/details/145001688

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!