likes
comments
collection
share

Redis 的高可用之Redis Cluster 集群模式

作者站长头像
站长
· 阅读数 14

一、Redis Cluster 集群是什么

1.1 Redis Cluster 集群诞生的背景

哨兵模式基于主从模式,实现读写分离,它还可以自动切换,系统可用性更高。

但是它每个节点存储数据是一样,浪费内存,并且不好在线扩容

因此,Reids Cluster 集群(切片集群实现方案)应运而生,它在 Redis3.0 加入,实现了 Redis 分布式存储。

比如你一个 Redis 实例保存 15G 甚至更大数据,响应就会很慢,这是因为Redis RDB 持久化机制导致,Redis 会 fork 子进程完成 RDB 持久化操作,fork 执行耗时与 Redis 数据量成正相关;这就引起了下面三个问题。

Redis 单节点限制
容量限制
高可用性
并发性能

这时候你很容易想到,把 15G 数据分散来存储就好了嘛。这就是 Redis 切片集群初衷。切片集群是啥呢?来看个例子,如果你要用 Redis 保存 15G 数据,可以用单实例 Redis,或者 3 台 Redis 实例组成切片集群,对比如下:

单例Redis

客户端
Redis,15G数据

切片集群

客户端
Redis1,5G数据
Redis2,5G数据
Redis3,5G数据

切片集群和 Redis Cluster 区别:Redis Cluster 是从 Redis3.0 版本开始,官方提供一种实现切片集群方案。

1.2 Redis Cluster 集群定义

Redis Cluster是Redis数据库的集群解决方案,用于将数据分布在多个节点上,实现分布式存储和处理。它通过自动分片和数据复制来提供高可用性和容错性。

实现了分布式的数据存储和处理,提供了高可用性、容错性和扩展性的优势,使得Redis能够在大规模应用中应对高并发和大数据量的需求。

Redis Cluster的主要特点包括:

Redis Cluster主要特点
分布式存储
数据复制
自动分片和故障转移
节点间通信
  • 分布式存储:Redis Cluster将数据分散存储在多个节点上,每个节点负责存储和处理其中的一部分数据。这种分布式存储方式允许集群处理更大的数据集,并提供更高的性能和可扩展性。

  • 数据复制:每个主节点都有一个或多个从节点,从节点会自动复制主节点上的数据。数据复制可以提供数据的冗余备份,并在主节点故障时自动切换到从节点,以保证系统的可用性。

  • 自动分片和故障转移:Redis Cluster会自动将数据分片到不同的节点上,同时提供自动化的故障检测和故障转移机制。当节点发生故障或下线时,集群会自动检测并进行相应的故障转移操作,以保持数据的可用性和一致性。

  • 节点间通信:Redis Cluster中的节点之间通过内部通信协议进行交互,共同协作完成数据的分片、复制和故障转移等操作。节点间通信的协议和算法确保了数据的正确性和一致性。

二、Redis Cluster 怎么处理实例和数据的映射关系的?

2.1 Redis Cluster使用哈希槽(hash slot)来管理实例和数据之间的映射关系

哈希槽是一个由0到16383之间的整数组成的空间,每个槽可以存放一部分数据。

当你向Redis Cluster中添加节点时,集群会自动分配哈希槽给每个节点。默认情况下,Redis Cluster有16384个哈希槽,每个节点负责一部分槽。

当你向Redis Cluster中写入数据时,Redis会使用一致性哈希算法来确定数据应该存储在哪个哈希槽中。具体的步骤如下:

1.根据数据的键,Redis Cluster使用CRC16算法计算出一个16位的哈希值
2.根据哈希槽索引,Redis Cluster确定存储该数据的节点
3.根据哈希槽索引,Redis Cluster确定存储该数据的节点

一旦数据被分配到了特定的节点,该节点就负责处理这个数据。当你进行读取操作时,Redis Cluster会根据数据的键计算哈希值,并将请求发送到负责该哈希槽的节点上。

2.2 示例

假设当前集群有 A、B、C 3 个节点,每个节点上负责哈希槽数 =16384/3,那么可能存在一种分配:

客户端
节点A
节点B
节点C
负责哈希槽0到5460
负责哈希槽5461到10922
负责哈希槽10923到16383

每个节点负责一部分哈希槽,确保数据在整个集群中均匀分布。在这种配置下,每个节点负责约1/3的哈希槽。

当你添加或移除节点时,Redis Cluster会自动重新分配哈希槽,以适应节点的变化。例如,如果你添加一个新节点,集群会将一部分哈希槽从现有节点迁移到新节点上,以保持数据的均衡性。

三、Redis Cluster中的哈希槽迁移是如何进行的?

3.1 Redis Cluster中的哈希槽迁移过程

在Redis Cluster中,哈希槽迁移是一个自适应的过程,它会根据集群的状态和负载情况动态进行,实现了数据的无损迁移和负载均衡。

哈希槽迁移是通过以下步骤进行的

两种同步方式
主流程
全量同步
增量同步
节点握手
哈希槽重分配
迁移数据同步
槽迁移确认
客户端重定向
  • 节点握手:当新节点加入Redis Cluster或者一个节点离开集群时,集群中的其他节点会与新节点建立握手连接。节点之间通过握手来交换集群拓扑信息和状态。

  • 哈希槽重分配:一旦握手完成,集群会开始进行哈希槽的重分配。这涉及到将一部分哈希槽从现有的负责节点(源节点)迁移到新的负责节点(目标节点)。哈希槽的迁移是逐个槽进行的,每次迁移一个槽。

  • 迁移数据同步:在哈希槽迁移期间,源节点会将属于目标节点负责的槽中的数据发送给目标节点。数据同步可以通过全量同步或增量同步来完成。

    • 全量同步:源节点将属于目标节点的槽中的所有数据发送给目标节点。这通常发生在初始迁移或网络断开后的重新连接时。

    • 增量同步:源节点将新写入的数据或数据更新发送给目标节点。这发生在全量同步完成后,源节点继续接收和处理写入操作时。

  • 槽迁移确认:目标节点在接收完数据后,会向源节点发送槽迁移确认消息,告知源节点迁移已完成。源节点收到确认后,将标记该槽已成功迁移。

  • 客户端重定向:在迁移过程中,客户端可能会尝试访问正在迁移的槽。为了确保数据一致性,Redis Cluster会向客户端发送重定向消息,告知客户端正确的目标节点地址,使其重新发送请求到正确的节点。

3.2 在哈希槽迁移期间,如果源节点发生故障会怎么样?

Redis Cluster有一套自己的故障转移机制,能够应对节点故障,并在故障发生后继续保持数据的可用性和一致性。

这种自动化的故障处理机制是Redis Cluster的一个关键特性,使得集群具备高可用性和容错性。

当源节点故障时,目标节点会触发故障转移(failover)机制,++选举出一个新的主节点来代替故障的源节点。选举过程涉及到Redis Cluster中的主节点投票和协调机制++。

一旦新的主节点选举完成,哈希槽迁移会继续进行:

新的主节点接管
客户端重定向
数据同步

新的主节点接管:新选举的主节点会接管原先故障节点负责的哈希槽。它会继续从源节点接收数据并完成哈希槽的迁移过程。

客户端重定向:与故障节点相关的哈希槽的客户端会收到重定向消息,告知它们新的主节点地址。客户端需要重新发送请求到新的主节点。

数据同步:如果故障的源节点在故障转移过程中恢复,它会作为一个从节点加入集群,并从新的主节点进行数据同步,以保持数据的一致性。

3.3 Redis Cluster如何确保数据在整个集群中的均匀分布?

Redis Cluster 是通过多种机制组合策略,来确保数据在整个集群中的均匀分布:

均匀策略
哈希槽分配
哈希槽迁移
一致性哈希算法
重新平衡
  • 哈希槽分配:Redis Cluster将所有的哈希槽(0到16383)均匀地分配给集群中的节点。每个节点负责一部分哈希槽,确保数据可以在节点之间平衡地存储。

  • 哈希槽迁移:当节点加入或离开集群时,Redis Cluster会自动进行哈希槽的迁移。迁移过程会调整节点负责的哈希槽范围,以达到数据的均衡分布。哈希槽迁移是自适应的,它会根据集群的状态和负载情况动态进行,确保数据在节点之间均匀分布。

  • 一致性哈希算法:Redis Cluster使用一致性哈希算法来确定数据应该存储在哪个哈希槽中。这种算法保证了相同的键(key)总是被映射到相同的哈希槽,从而保证了数据的一致性和均匀分布。

  • 重新平衡:Redis Cluster会定期检查节点的负载情况,并根据需要进行哈希槽的重新分配和迁移,以重新平衡数据的分布。这样可以避免出现某些节点负载过重而导致性能不均衡的情况。

四、MOVED 重定向和 ASK 重定向是干什么用的?

客户端给一个 Redis 实例发送数据读写操作时,如果这个实例上并没有相应数据,会怎么样呢?

嘿嘿,这就是MOVED 重定向和 ASK 重定向要干的事了;

先看看请求来了的处理流程:

1. 通过哈希槽映射,检查当前 Redis key 否存在当前节点
2. 若哈希槽不由自身节点负责,就返回 MOVED 重定向
3. 若哈希槽确实由自身负责,且 key 在 slot 中,则返回该 key 对应结果
4. 若 Redis key 不存在此哈希槽中,检查该哈希槽否正在迁出?
5. 若 Redis key 正在迁出,返回ASK 错误重定向客户端到迁移目服务器上
6. 若哈希槽未迁出,检查哈希槽否导入中?
7. 若哈希槽导入中且有 ASKING 标记,则直接操作,否则返回 MOVED 重定向

4.1 Moved 重定向

客户端给一个 Redis 实例发送数据读写操作时,如果计算出来槽不在该节点上,这时候它会返回 MOVED 重定向错误,MOVED 重定向错误中,会将哈希槽所在新实例 IP 和 port 端口带回去。这就 Redis Cluster MOVED 重定向机制。

流程图如下

客户端Redis Cluster源节点目标节点alt[哈希槽正常]alt[哈希槽正在迁移]发送命令(携带哈希槽)计算槽对应节点检查哈希槽状态执行命令返回结果返回MOVED错误响应解析重定向信息重新发送命令返回结果客户端Redis Cluster源节点目标节点

检查哈希槽状态:Redis Cluster 接收到命令后,会检查该命令涉及的哈希槽的状态。如果该哈希槽正在迁移过程中,即从源节点迁移到目标节点,那么 Redis Cluster 将会返回一个 MOVED 错误响应。

4.2 ASK 重定向

Ask 重定向一般发生于集群伸缩时候。集群伸缩会导致槽迁移,当我们去源节点访问时,此时数据已经可能已经迁移到了目标节点,使用 Ask 重定向可以解决此种情况。

流程图如下

客户端Redis Cluster源节点目标节点alt[哈希槽正常]alt[哈希槽正在迁移]发送写入命令(携带哈希槽)计算槽对应节点检查哈希槽状态执行写入操作返回结果返回ASK错误响应解析重定向信息重新发送写入命令返回结果客户端Redis Cluster源节点目标节点

检查哈希槽状态:Redis Cluster 接收到写入命令后,会检查该命令涉及的哈希槽的状态。如果该哈希槽正在迁移过程中,即从源节点迁移到目标节点,但迁移尚未完成,那么 Redis Cluster 将会返回一个 ASK 错误响应。

五、使用Redis Cluster 有什么需要注意的?

  • 数据分片和哈希槽:Redis Cluster 使用数据分片和哈希槽来实现数据的分布式存储。每个节点负责一部分哈希槽,确保数据在集群中均匀分布。在设计应用程序时,需要考虑数据的分片规则和哈希槽的分配,以便正确地将数据路由到相应的节点。

  • 节点的故障和扩展:Redis Cluster 具有高可用性和可伸缩性。当节点发生故障或需要扩展集群时,需要正确处理节点的添加和删除。故障节点会被自动检测和替换,而添加节点需要进行集群重新分片的操作。

  • 客户端的重定向:Redis Cluster 在处理键的读写操作时可能会返回重定向错误(MOVED 或 ASK)。应用程序需要正确处理这些错误,根据重定向信息更新路由表,并将操作重定向到正确的节点上。

  • 数据一致性的保证:由于 Redis Cluster 使用异步复制进行数据同步,所以在节点故障和网络分区恢复期间,可能会发生数据不一致的情况。应用程序需要考虑数据一致性的问题,并根据具体业务需求采取适当的措施。

  • 客户端连接的负载均衡:在连接 Redis Cluster 时,应该使用适当的负载均衡策略,将请求均匀地分布到集群中的各个节点上,以避免单个节点过载或出现热点访问。

  • 事务和原子性操作:Redis Cluster 中的事务操作只能在单个节点上执行,无法跨越多个节点。如果需要执行跨节点的原子性操作,可以使用 Lua 脚本来实现。

  • 集群监控和管理:对 Redis Cluster 进行监控和管理是很重要的。可以使用 Redis 自带的命令行工具或第三方监控工具来监控集群的状态、性能指标和节点健康状况,以及执行管理操作,如节点添加、删除和重新分片等。

5.1 有没有推荐的负载均衡策略可以在Redis Cluster中使用?

在 Redis Cluster 中,可以采用以下几种负载均衡策略来分发客户端的请求:

负载均衡策略
随机选择节点
轮询选择节点
哈希分片选择节点
基于节点负载的选择
一致性哈希选择节点
  • 随机选择节点:每次请求随机选择一个节点来处理。这种策略简单且易于实现,但++无法考虑节点的负载情况++。

    • 适用于负载均衡要求不高的场景
  • 轮询选择节点:按照轮询的方式依次选择节点来处理请求。这样可以均匀地将请求分发到各个节点上,但++无法考虑节点的负载情况++。

    • 适用于节点负载相对均衡的场景。
  • 哈希分片选择节点:根据请求的键进行哈希计算,将相同哈希值的请求分发到同一个节点上。这样可以保证相同键的请求总是落到同一个节点上,但++无法考虑节点的负载情况++。

    • 适用于节点负载相对均衡的场景。
  • 基于节点负载的选择:通过监控节点的负载情况(如 CPU 使用率、内存使用率等),选择负载较低的节点来处理请求。这种策略++需要实时监控节点的状态++,并根据实际负载情况进行动态调整。

  • 一致性哈希选择节点:使用一致性哈希算法将请求的键映射到节点,确保在节点添加或删除时,尽量减少键的迁移量。这种策略可以提供较好的负载均衡和节点扩展性,但++可能导致不均匀的数据分布++。

    • 适用于节点负载相对均衡的场景。