Redis-Cluster是一个去中心的分布式Redis存储架构,解决了Redis高可用、可扩展等问题。
集群
redis-cluster采用分片机制,将整个集群分为16384个槽(slot),默认平均分配在集群各个节点上。
每个节点负责维护一部分槽以及槽所映射的键值对
分片算法: slot=CRC16(KEY)%16384
请求流程
将请求发送到任意节点,接收到请求的节点将查询请求转发到正确的节点上执行,即redis会返回转向指令,类似302跳转
一致性
主从节点依然存在数据不一致的问题
容错
redis-cluster采用replica方式冗余一定节点做slave,当某台主节点fail后在从节点中通过选举算法重新得出主节点。
如果该节点及其slave节点都fail掉,则整个集群状态变为fail
故障检测
主观下线
集群中每个节点会定期向其他节点发送ping消息,接收节点恢复pong消息作为响应。如果在cluster-node-timeout时间内通信与某台节点ping-pong通信一直失败,则发送节点会认为接收节点存在故障并将接受节点标记为主观下线pfail
客观下线
当某个节点判断另一个节点主观下线后,相应的节点状态会跟随消息在集群内传播。通过gossip消息传播,集群内节点不断收集到故障节点的下线报告。当半数以上持有槽的主节点都标记某个节点是主观下线时,触发客观下线流程
- 首先统计有效的下线报告数量,如果小于集群内持有槽的主节点总数的一半则退出
- 当下线报告数量大于槽主节点数量一半时,标记对应故障节点为客观下线状态
- 向集群广播一条fail消息,通知所有节点将故障节点标记为客观下线,fail消息的消息体只包含故障节点的id
广播fail消息
广播fail消息是客观下线的最后一步,它承担着非常重要的职责
- 通知集群内所有节点标记故障节点为客观下线并立即生效
- 通知故障节点的从节点触发故障转移流程
注意:容错的过程中集群会短暂down的时间段 集群状态变化ok->fail->ok
节点超时选项:cluster-node-timeout,默认15秒
故障转移
当一个从节点发现自己正在复制的主节点进入下线状态时,从节点将开始对下线主节点进行故障转移
- 下线主节点n0的所有从节点中选中其中一个n1(选举)
- n1节点执行SLAVEOF NO ONE,成为新的主节点
- 新主节点n1节点会撤销所有对n0节点的槽指派,并将这些槽全部指派给自己
- 新的主节点n1向集群广播一条PONG消息,这条PONG消息可以让集群中的其他结点立即知道这个节点已经由从节点变成主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽
- 新的主节点开始接收和自己负责的槽有关的命令操作
读写能力优化
redis-cluster中master用于读写,slave节点用于备份。如果不介意读取的是有可能过期的数据,并且对写请求不感兴趣时,看通过readonly命令,将slave设置为可读。
不过redis-cluster中master其实是可以任意扩展的,扩容master其实是比扩容slave效果更好的方式
优缺点分析
redis-cluster集群方式优点是解耦了数据与节点之间的关系,简化了节点扩容和收缩难度
缺点如下:
1.key是数据分区最小粒度,不能将一个大的键值对象,如hash等映射到不同节点上
2.集群下只能使用db0
3.事务支持有限,只支持同一个节点上的多个key的事务操作
4.key批量操作支持有限,只支持具有相同slot值的key执行批量操作
常用命令
|
|
实操
|
|
FAQ
1.为什么redis-cluster的槽数为16384个
- 可以减小心跳包的大小。槽数为16384时,心跳包槽状态信息占用2k字节空间;槽数为63336个时,心跳包槽状态信息占用8k字节空间。
- redis-cluster集群节点数量不建议超过1000个
因此使用16384个槽既可以减小心跳包带来的带宽浪费,又可以满足绝大多数场景(1000个节点以内)