1. 数据分布
1.1 数据分布理论
- 哈希分区:离散度好,数据分布业务无关
- 顺序分区:离散度易倾斜,数据分布业务相关,可顺序访问
-
节点取余分区:hash(key)%N,当节点数量变化时,映射关系需重新计算,会导致数据迁移,通常翻倍扩容
-
一致性哈希分区:为系统中每个节点分配一个token,构成一个哈希环
- 加减节点会造成部分数据失效
- 不适合少量节点
-
普通的一致性哈希分区在增加节点时要增加一倍或减去一半才能保证数据负载均衡
一致性哈希.jpg
-
虚拟槽分区:使用分散度良好的哈希函数把所有数据映射到一个固定的整数范围0~16383,5个节点的话,每个节点平均负责3276个槽
槽集合.jpg
1.2 Redis数据分区
采用虚拟槽分区,slot = CRC16(KEY)&16383,特点:
- 解耦数据和节点之间的关系,简化节点扩容和收缩难度
- 节点自身维护槽的映射关系
- 支持节点、槽、键支架你的映射查询
1.3 集群功能限制
- key批量操作支持有限
- key事务操作支持有限
- key作为数据分区的最小粒度
- 不支持多数据库空间
- 复制结构只支持一层
2. 搭建集群
2.1 准备节点
至少6个节点,开启cluster-enable yes
2.2 节点握手
一批运行在集群模式下的节点通过Gossip协议彼此通信
客户端执行命令:
cluster meet 127.0.0.1 6380
2.3 分配槽
通过一下命令为节点分配槽
cluster addslots {0...5461} //分配槽
cluster replicate cfb.... //命令一个节点称为从节点
2.4 使用redis-trib.rb搭建集群
采用Ruby实现的Redis集群管理工具
3. 节点通信
3.1 通信流程
分布式存储中提供维护节点元数据信息的机制
1 集中式
2 P2P方式
Redis集群采用P2P的Gossip(流言)协议,节点彼此不断通信交换信息,类似流言传播
- 集群中每个节点单独开辟一个TCP通道,用于节点之间彼此通信
- 每个节点在固定周期内通过特定规则选择几个节点发送ping消息
- 接收到ping消息的节点用pong响应
3.2 Gossip消息
- ping 检测节点是否在线和交换信息
- pong 响应ping
- meet 通知新节点加入
- fail 判定有节点下线,广播fail消息
3.3 节点选择
Redis集群呢节点通信采用固定频率,每次选择需要通信的节点,选多了会成本过高,选少了会降低信息交换频率,Gossip协议需要兼顾信息交换实时性和成本开销。
选择通信节点规则.jpg- 选择发送消息的节点数量 5 + 10*num(node.pong_received > cluster_node_timeout/2)
- 消息数据量
4. 集群伸缩
4.1 伸缩原理
通过指令,每个节点把一部分槽和数据迁移到新的节点,即:
集群伸缩 = 槽和数据在节点之间的移动
4.2 扩容集群
- 准备新节点
- 加入集群
- 迁移槽和数据(或是作为从节点负责故障转移)
4.3 收缩集群
- 下线迁移槽
- 忘记节点
cluster forget {downNodeId}
5. 请求路由
Redis集群为了追求性能最大化,采用客户端直连节点而不是代理的方式
5.1 请求重定向
重定向流程.jpg- 计算槽
- 槽节点查找
5.2 Smart客户端
Smart客户端通过在内部维护slot->node的映射关系,本地就可实现键到节点的查找,而move重定向负责协助smart客户端更新slot->node映射
Jedis客户端命令执行流程.jpg5.3 ASK重定向
当slot对应的数据在迁移过程中,可能一部分数据在源节点,另一部分在目标节点,客户端需要智能识别
- 客户端根据本地slots缓存,发送命令到源节点
- 如果键对象不存在,可能存在于目标节点,源节点恢复ASK重定向异常
- 客户端从ASK重定向信息中提取目标节点信息,发送asking命令道目标节点
为了支持ASK重定向,源节点和目标节点在内部的clusterState结构中维护当前正在迁移的槽信息,用于识别槽迁移情况
6. 故障转移
解决集群部分失败场景,自动故障转移
6.1 故障发现
- 主观下线:某个节点认为另一个节点不可用
- 客观下线:标记一个节点真正下线,多个节点认为此节点不可用达成共识
广播fail消息是客观下线最后一步,通知集群内所有节点标记故障节点为客观下线并立刻生效
通知故障节点的从节点触发故障转移流程
6.2 故障恢复
- 从节点资格检查
- 准备选举时间
- 发起选举
- 选举投票
- 替换主节点
6.3 故障转移时间
- 主观下线识别时间 = cluster-node-timeout
- 主观下线消息传播时间 <= cluster-node-timeout/2
- 从节点转移时间<=1000毫秒
7. 集群运维
- 集群完整性,所有槽都被分配
- 带宽消耗,考虑集群内Gossip消息通信
- Pub/Sub广播问题,发布订阅加重带宽负担
- 集群倾斜,不同节点间数据量和请求量出现明显差异:数据倾斜,请求倾斜
- 集群读写分离
- 手动故障朱阿姨
- 数据迁移
网友评论