目录
- Redis系列-Redis集群模式【8】
- 特性
- Redis的数据分区
- 虚拟槽分区
- Redis虚拟槽分区的特点
- 客户端如何定位目标节点?
- 故障转移
- 故障检测
- 故障转移
- Redis一致性保证
- Redis集群的功能限制
- 部署命令
- REF
个人主页: 【⭐️个人主页】
需要您的【💖 点赞+关注】支持 💯
Redis系列-Redis集群模式【8】
在 Redis 3.0 之前,使用 哨兵(sentinel)机制来监控各个节点之间的状态。
Redis Cluster 是 Redis 的 分布式解决方案,在 3.0 版本正式推出,有效地解决了 Redis 在 分布式 方面的需求。当遇到 单机内存、并发、流量 等瓶颈时,可以采用 Cluster 架构方案达到 负载均衡
的目的。
Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
Redis 集群提供了以下两个好处:
- 将数据自动切分(split)到多个节点的能力。
- 当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。
特性
Redis集群的几个重要特征:
- 去中心化,主节点关系对等
- 解决了数据扩容
- 客户端与服务端缓存槽位信息,以服务端为准,客户节点缓存主要为了避免连接切换
- 可人为迁移数据
- 主节点处理读写命令
Redis的数据分区
Redis Cluster 采用 虚拟槽分区
,所有的键
根据 哈希函数
映射到 0~16383
整数槽内,计算公式:slot = CRC16(key)& 16383
。每个节点负责维护一部分槽以及槽所映射的 键值数据,如图所示:
虚拟槽分区
虚拟槽分区 巧妙地使用了 哈希空间,使用 分散度良好 的 哈希函数 把所有数据 映射 到一个 固定范围 的 整数集合 中,整数定义为 槽(slot)。
这个范围一般远远大于节点数,比如 Redis Cluster 槽范围是 0 ~ 16383。槽是集群内数据管理和迁移的基本单位。采用大范围槽的主要目的是为了方便数据拆分和集群扩展。每个节点会负责 一定数量的槽,如图所示:
当前集群有 5 个节点,每个节点平均大约负责 3276 个 槽。由于采用 高质量 的 哈希算法,每个槽所映射的数据通常比较 均匀,将数据平均划分到 5 个节点进行 数据分区。Redis Cluster 就是采用 虚拟槽分区。
节点1: 包含 0 到 3276 号哈希槽。
节点2:包含 3277 到 6553 号哈希槽。
节点3:包含 6554 到 9830 号哈希槽。
节点4:包含 9831 到 13107 号哈希槽。
节点5:包含 13108 到 16383 号哈希槽。
这种结构很容易添加或者删除节点。如果增加 一个节点 6,就需要从节点 1 ~ 5 获得部分槽分配到节点 6 上。如果想移除节点 1,需要将节点 1 中的 槽 移到节点 2 ~ 5 上,然后将没有任何槽 的节点 1 从集群中移除即可。
由于从一个节点将 哈希槽
移动到另一个节点并不会 停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。
Redis虚拟槽分区的特点
解耦数据和节点之间的关系,简化了节点扩容
和收缩难度
。
节点自身 维护槽的 映射关系,不需要客户端或者代理服务维护槽分区元数据
。
支持 节点、槽、键 之间的 映射查询,用于 数据路由
、在线伸缩
等场景。
客户端如何定位目标节点?
当 redis cluster 的客户端来连接集群时,会得到一份集群的槽位配置信息。这样当客户端要查找某个 key 时,可以直接定位到目标节点。
客户端为了可以直接定位
(对 key 通过 crc16 进行 hash 再对 214 取余 crc16(key)% 16384
)某个具体的 key 所在节点,需要缓存槽位相关信息
,这样才可以准确快速地定位到相应的节点
。同时因为可能会存在客户端与服务器存储槽位的信息不一致的情况,还需要纠正机制
(比如通过返回 -MOVED 3999 127.0.0.1:6479 ,客户端收到后需要立即纠正本地的槽位映射表)来实现槽位信息的校验调整
。
另外,redis cluster 的每个节点会将集群的配置信息持久化到配置文件中,这就要求确保配置文件是可写的,而且尽量不要依靠人工修改配置文件。
故障转移
cluster 集群中节点分为主节点和从节点,其中主节点用于处理槽,而从节点则用于复制该主节点,并在主节点下线时,代替主节点继续处理命令请求。
故障检测
集群中每个节点都会定期地向集群中的其他节点发送 ping
消息,如果接收 ping
消息的节点没有在规定时间内回复 pong
消息,那么这个没有回复 pong
消息的节点会被标记为 PFAIL
(probable fail)。
集群中各个节点会通过互相发送消息的方式来交换集群中各个节点的状态信息;如果在一个集群中,半数以上负责处理槽的主节点都将某个主节点 A 报告为疑似下线,那么这个主节点 A将被标记为下线( FAIL
);标记主节点 A 为下线状态的主节点会广播这条消息,其他节点(包括A节点的从节点)也会将A节点标识为FAIL
;
故障转移
当从节点发现自己的主节点进入 FAIL
状态,从节点将开始对下线主节点进行故障转移:
- 从数据最新的从节点中选举为主节点;
- 该从节点会执行 replica no one 命令,称为新的主节点;
- 新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己;
- 新的主节点向集群广播一条
pong
消息,这条pong
消息可以让集群中的其他节点立即知道这个节点已经由从节点变成主节点,并且这个主节点已经接管了之前下线的主节点; - 新的主节点开始接收和自己负责处理的槽有关的命令请求,故障转移结束
Redis一致性保证
Redis 并不能保证数据的强一致性
. 这意味这在实际中集群在特定的条件下可能会丢失写操作: 原因是因为集群是用了异步复制
.
主从异步复制在故障转移时仍存在数据丢失的问题
Redis集群的功能限制
Redis 集群相对 单机
在功能上存在一些限制,需要 开发人员 提前了解,在使用时做好规避。
-
key 批量操作支持有限。
类似 mset、mget 操作,目前只支持对具有相同 slot 值的 key 执行 批量操作。对于 映射为不同 slot 值的 key 由于执行 mget、mget 等操作可能存在于多个节点上,因此不被支持。
-
key 事务操作支持有限。
只支持 多 key 在 同一节点上 的 事务操作,当多个 key 分布在 不同 的节点上时 无法 使用事务功能。
-
key 作为数据分区的最小粒度
不能将一个 大的键值 对象如 hash、list 等映射到 不同的节点。
-
不支持多数据库空间
单机下的Redis可以支持 16 个数据库(db0 ~ db15),集群模式 下
只能使用一个数据库空间
,即 db0。 -
复制结构只支持一层
从节点
只能复制主节点
,不支持嵌套树状复制
结构。
部署命令
redis-cli --cluster help
# 创建集群
create <ip>:<port>
--cluster-replicas <num> # 创建集群的同时,为每个主节点配备的从节点个数
# 查看集群的信息,群中任意节点地址作为参数,后面同理
info <ip>:<port>
# 检查集群的配置
check <ip>:<port>
# 重分片,将指定数量的槽从源节点迁移至目标节点,由目标节点负责迁移的槽和槽中数据
reshared <ip>:<port>
--cluster-from # 源节点的ID
--cluster-to # 目标节点的ID
--cluster-slots <num> # 需要迁移的槽数量
# 添加节点,添加新节点 new 集群 existing,默认添加主节点
add-node <new_host>:<port> <existing_host>:<port>
# 添加从节点,需要以下两个子命令
--cluster-slave
--cluster-master-id <id> # 设置从节点要复制的主节点
# 移除节点
del-node <ip>:<port> <id>
REF
https://zhuanlan.zhihu.com/p/391762630
https://blog.csdn.net/xgw1010/article/details/108388592