版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Francis123580/article/details/82530457
Redis 数据分区
Redis Cluster 采用虚拟槽分区,所有键根据哈希函数映射到 0 - 16383 整数槽内,每一个节点负责维护一部分槽以及槽所映射的键值数据
特点:
- 解耦数据和节点之间的关系,简化了节点扩容和收缩难度
- 节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据
- 支持节点、槽、键之间的映射查询,用于数据路由、在线伸缩等场景
集群功能限制
- key 批量操作支持有限,对于mset、mget等操作可能存在多个节点因此不被支持
- key 事务操作支持有限,只支持多key在同一节点上的事务操作
- key 作为数据分区的最小粒度,不能讲一个大的键值对象(hash、list)映射到不同节点
- 不支持多数据库空间,集群下Redis只能使用一个数据库空间
- 复制结构只支持一层,从节点只能复制主节点,不支持嵌套树状复制结构
搭建集群
准备节点
- 每个节点开启配置
cluster-enabled yes
- 启动6个节点
节点握手
- 由客户端发起命令
cluster meet {ip} {port}
- 对节点分别执行
cluster nodes
命令,各节点可以感知彼此存在 - 查看集群当前状态
cluster info
分配槽
- 通过
cluster addslots
命令为节点分配槽 - 使用
cluster replicate {nodeId}
命令节点复制对应的主节点
节点通信
通信流程
Redis 采用P2P的Gossip协议维护元数据
- 集群中每个节点都开辟一个TCP通道,用于节点之间彼此通信
- 每个节点在固定周期内通过特定规则选择几个节点发送ping消息
- 接收到ping消息的节点用pong消息作为响应
Gossip消息
- meet消息:用于通知新节点加入
- ping消息:集群内每个节点每秒向多个其它节点发送,检测节点是否在线
- pong消息:作为响应消息回复给发送方确认消息正常通信
- fail消息:当节点判定集群内另一个节点下线,会想集群内广播一个fail消息
节点选择
- 选择发送消息的节点数量:每秒执行10次,随机选取5个节点找到最久没有通信节点发送ping消息
- 消息数据量:每个ping消息 消息头占用2KB左右,消息体视集群节点数量
集群伸缩
扩容集群
- 准备新节点:准备2个新节点,保持和集群内配置一致,启动节点
- 加入集群:在集群内任意节点执行
cluster meet ip port
- 迁移槽和数据:制定槽迁移计划,用命令进行数据迁移,添加从节点
收缩集群
- 下线迁移槽:把负责的槽迁移到其它节点
- 忘记节点:通知集群内其它节点忘记下线节点,当其它节点忘记后则可关闭
请求路由
请求重定向
- 计算槽:根据键的有效部分使用CRC16函数计算出散列值,再取对16383的余数,使每个键都可以映射到 0 - 16383 槽范围内
- 槽节点查找:Redis计算得到的键对应的槽后,需要查找槽对应的节点。集群内通过消息交换每个节点都会知道所有节点的槽信息
Smart 客户端
- Smart客户端通过在内部维护 slot —> node 的映射关系,本地就可以实现键到节点的查找,从而保证IO效率的最大化
- MOVED 重定向负责协助Smart客户端更新 slot —> node 映射
ASK 重定向
- 客户端ASK重定向流程,ASK重定向说明集群正在slot数据迁移
- 节点内部处理:检查是否正在迁出;批量操作会受到影响
故障转移
故障发现
- 主观下线:节点a内的定时任务检测到与节点b的最后通信时间超过cluster-node-timeout,则更新本地对节点b的状态为主观下线
- 客观下线:当某个节点判断另一节点主观下线后,节点状态会在集群内传播,当半数以上持有槽的主节点都标记主观下线,触发客观下线流程
故障恢复
- 资格检查:根据从节点与主节点断线时间判断是否具备故障转移资格
- 准备选举时间:符合故障转移资格后,更新故障选举时间,达到时间后执行后续流程
- 发起选举:更新配置纪元、广播选举消息
- 选举投票:只有持有槽的主节点才会处理故障选举消息
- 替换主节点:当前从节点变成主节点,撤销故障主节点的槽,把这些槽委派给自己,然后向集群广播自己的消息