1 集群的意义
Redis集群不断发展,可实现在多台机器,部署多实例,每个实例存部分数据。
同时每个实例可以带上Redis从实例,保证若Redis主实例挂了,自动切换到redis从实例。
上古时代,很多用codis之类客户端支持集群。现在版本大家都用Redis cluster,即官方提供的集群模式,必须深入研究了。
从单机的一主多从复制架构到现在的分布式架构
主要有如下维度:
业务
追求更高QPS
数据量
Scale Up已经无法满足,超过了单机极限,考虑Scale Out分布式。
Redis内存淘汰策略,保证不可能超过master节点内存阈值。master节点数据和slave节点的数据保持一致。
一个redis即可横向扩容了。若要支撑更大数据缓存,就横向扩容更多master节点,每个master节点就能存放更多数据。单台服务器32G,30台即可达1TB。
网络流量
业务流量超过服务器网卡上限,考虑分布式分流
离线计算
需要中间环节缓冲等需求
2 meet
节点之间完成相互通信的基础,有一定的频率和规则。
CLUSTER MEET命令被用来连接不同的开启集群支持的 Redis 节点,以进入工作集群。
2.1 基本思想
每个节点默认互不信任,并且被认为是未知节点,以防系统管理错误或地址被修改,而不太可能将多个不同的集群节点混成一个集群。
因此,为了使给定节点能将另一个节点接收到组成 Redis Cluster 的节点列表中,这里只有两种方法:
系统管理员发送一个CLUSTER MEET命令强制一个节点会见另一个节点
一个已知节点发送一个保存在 gossip 部分的节点列表,包含着未知节点。如果接收的节点已经将发送节点信任为已知节点,它会处理 gossip 部分并且发送一个握手消息给未知的节点。
Redis Cluster 需要形成一个完整的网络(每个节点都连接着其他每个节点),但为创建一个集群,不需要发送形成网络所需的所有CLUSTER MEET命令。发送CLUSTER MEET消息以便每个节点能够到达其他每个节点只需通过一条已知的节点链就够了。由于在心跳包中会交换 gossip 信息,将会创建节点间缺失的链接。
所以,如果我们通过CLUSTER MEET链接节点 A 和 B ,并且 B 和 C 有链接,那么节点 A 和 C 会发现他们握手和创建链接的方法。
2.2 案例
假设某一集群有A、B、C、D四个节点,可以只发送以下一组命令给 A :
CLUSTER MEET B-ip B-port CLUSTER MEET C-ip C-port CLUSTER MEET D-ip D-port
由于 A 知道及被其他所有节点知道,它将会在发送的心跳包中包含gossip部分,这将允许其他每个节点彼此都创建一个链接,即使集群很大,也能在数秒内形成一个完整网络。
CLUSTER MEET无需相互执行,即若发送命令给 A 以加入B ,那就不必也发送给 B 以加入 A。
由于 A 知道及被其他所有节点知道,它将会在发送的心跳包中包含gossip部分,这将允许其他每个节点彼此都创建一个链接,即使集群很大,也能在数秒内形成一个完整网络。
CLUSTER MEET无需相互执行,即若发送命令给 A 以加入B ,那就不必也发送给 B 以加入 A。
2.3 实现细节:MEET 和 PING 包
当某一给定节点接收到一个MEET消息时,命令中指定的节点仍不知发送了该命令,所以为使节点强制将接收命令的节点将它作为信任的节点接受它,它会发送MEET包而非PING包。两个消息包有相同的格式,但是MEET强制使接收消息包的节点确认发送消息包的节点为可信任的。
3 指派槽
把16384个槽平分给节点管理,每个节点只对自己负责的槽进行读写。
每个节点间都相互通信,所以每个节点都知道其它节点所管理槽的范围
客户端与指派槽
4 集群伸缩
集群的伸缩包括新节点的加入和旧节点退出。
4.1 加入新节点
- 准备新节点
启动一个集群模式下的Redis节点 - 加入集群
通过与任意一集群中的节点握手加入新节点 - 迁移slot到新节点
再向新节点分配它负责的slot并向其迁移slot对应数据。 - 由于Redis采用Gossip协议,所以可让新节点与任一现有集群节点握手,一段时间后整个集群都会知道加入了新节点。
4.1.1 案例
向如下集群中新加入一个节点6385。由于负载均衡的要求,加入后四个节点每个节点负责4096个slots,但集群中原来的每个节点都负责5462个slots,所以6379、6380、6381节点都需要向新的节点6385迁移1366个slots。
Redis集群并没有一个自动实现负载均衡的工具,把多少slots从哪个节点迁移到哪个节点完全是由用户指定。
迁移数据的流程图
- 迁移key可以用pipeline进行批量的迁移。
对于扩容,原理已经很清晰了,至于具体操作,网上很多。
至于缩容,也是先手动完成数据迁移,再关闭redis。收缩时如果下线的节点有负责的槽需要迁移到其他节点,再通过cluster forget命令让集群内所有节点忘记被下线节点