* 需求背景
1、扩展性:单机内存资源有限,要动态地节点扩容、节点缩容;
2、主从、数据备份和容灾;
3、redis是单线程io结构,多核结构的server发挥不到作用;
方案有:client sharding、twemproxy、redis cluster、proxy+redis cluster;----> codis proxy+zookeeper/nginx+redis
需求: Redis集群方案
1、支持数据分片;
2、主从备份,支持主从自动切换;
3、读请求负载均衡;
4、支持节点failover,数据自动迁移;
功能
1、节点自动发现
* 通过客户端meet消息,把节点加入集群中;
* 每个节点每秒从已知节点中随机选五个节点,发送ping pong消息,当接收者有选中节点,更新对这个节点的认知;如果没有选中节点的信息,接受者与被选中节点进行握手;
* 一个节点可以通过向集群广播自己的pong消息让集群中的其他节点立即刷新关于这个节点的认识;
* slave节点发现用cluster replicate node_id,通过消息发送给集群中其他节点,最终让其他集群节点感知到;
2、命令请求分配到不同节点集群处理
* key 做 crc(key)&16383 -->得到槽位;
* 为每个节点分配槽位信息,并且传播节点槽位指派信息给其他节点,且每个节点有一个全局记录每个槽位对应的处理节点信息(cluster_node);
* 当命令给的节点不是对应的槽为处理节点,向客户端发送moved错误,重定位节点;
3、节点备份 复制
4、故障迁移 slave节点转移为master节点,从节点选举为主节点
* 故障检测机制:每个节点定期向其他节点发ping消息,规定time内是否返回pong;如果超时,疑似下线pfail,疑似下线有fail_report,有疑似下线报告;
* 集群中的各个节点会通过互相发送消息的方式来交换急群众的各个节点的状态信息,例如某个节点处于下线状态、疑似下线状态、还是已经下线状态;
*在集群中,半数以上负责槽位的节点将主节点x报告为pfail,这个主节点x将标志为fail;标志为主节点x为下线的节点立即向集群广播一条关于x的fail消息,所有接收到fail消息的节点,就立即将x节点标志位fail;
* 选举新主节点:slave节点检测到下线fail,立即广播clustermsg_type_failover_ath_request消息,之后收到其他主节点clustermsg_type_failover_auth_ok消息;当收到clustermsg_type_failover_auth_ok消息数大于等于N/2+1,就被选举为主节点;
* 故障迁移:被选为主节点的从节点自己进行故障转移操作,新主节点自己执行slaveof no one;槽位接管;当数据迁移及槽位接管后,向其他主节点广播pong消息,让其他节点认识新的节点;
5、扩容 缩容
* redis-trib setslot
* redis-trib setslot
* 源节点是否保存了术语slot的键值,如果有,将键全部迁移到目标节点;最后将slot指派给目标节点,广播slot重分配消息告知slot分配给了目标节点;
* 在槽位重分配的过程中,slot的键值对可能存在两个节点中,ask错误,指引客户端转向target目标节点;
* 集群中gossip协议,节点发现;^_^
* 数据分片,向集群发送不同key的消息;^_^
* 扩容 缩容 槽位迁移;^_^
* 故障检测 从节点选举 和数据迁移^_^
此图截图来源于书籍《redis 设计与实现》黄健宏著
* 设置key-value和获取key-value
此图截图来源于书籍《redis 设计与实现》黄健宏著
* 数据迁移:key-value的迁移是客户端控制的,用migrate命令把key-value迁移到指定的槽位;
*向目标节点发送cluster setslot
* 对源节点发送 cluster setslot
* 向源节点发送 cluster getkeysinslot
* 对于每个得到的键名,向源节点发送一个migrate
* 最后,向集群的任意一个节点发送cluster setslot
此说明主要参考书籍《redis 设计与实现》黄健宏著