Redis Cluster 扩容
接着上一篇Redis Cluster 单机集群部署,今天学习下Redis Cluster 架构在实际应用中如何面对各种复杂的场景,如:
- 扩容 - 增加节点
- 缩减 - 删除节点
- 宕机 - 主节点服务异常
增加节点
随着集群需求的变化,系统人员可能需要通过修改Redis Cluster中shard的数量来提高性能,或者降低成本,由此产生Redis Cluster 集群扩展的需求。 对Redis Cluster 集群进行缩减、扩容的条件包含:
- 内存压力 - 集群节点内存占用过高 需要更多的资源来存储数据
- CPU瓶颈 - 单机CPU负载过高 请求处理延迟 需要新增节点 分散CPU 计算瓶颈
- 网络瓶颈 - 大并发场景 网络带宽存在上限限制 需要新增节点 分散网络流量瓶颈
- 集群规模过大 - 需要缩小进群规模 以降低服务器成本
Redis Cluster 支持两种方式对集群进行扩展
- 横向扩展 - 水平横向扩展允许通过添加、删除节点数量,对数据进行重新分配
- 纵向扩展 - 通过增加主节点的副本数 达到高可用的架构设计目标
横向扩展 - 增加节点
在之前已经搭建好的三主三从的的Cluster 架构中新增一个主节点 node_6006.
# 127.0.0.1:6006 表示新加入的节点
# 127.0.0.1:6000 表示当前存在的主节点
redis-cli --cluster add-node 127.0.0.1:6006 127.0.0.1:6000
集群信息
# 使用命令查看集群状态 确认节点已经加入进来
redis-cli -p 6000 cluster nodes
纵向扩展 - 增加副本
启动6007节点,将他加入集群中,并作为6007的从节点,同步数据
redis-cli --cluster add-node 127.0.0.1:6007 127.0.0.1:6000 --cluster-slave --cluster-master-id 3785af3f1f395e28a66a06e9c73305cbde59f1ba
已经在集群的基础上正确的添加了2个节点,一主一从。此时整个Redis Cluster 集群共有8个节点,四主四从。但是从上图红线处可知,新增的6006主节点并没有分配Hash槽,也就是实际上它并不能分担整个集群的数据存储功能。
# 使用一下命令 查看Cluster 集群 slot信息
redis-cli -p 6000 cluster slots
从slot的信息中也看出来6006节点并没有体现,也进一步验证了之前的判断。
数据分配
在对集群数据进行重新分配之前,需要思考以下问题:
-
新节点分配多少数据 - 目前有4个节点,Redis Cluster总共有16384个hash槽,简单粗暴的进行过平均计算,那么每个节点有4096个hash槽。
-
数据往哪里分发 - Redis Cluster 集群需要知道节点具体的节点ID 来接收4096个hash 槽数据
# 通过命令获取 新增节点的ID redis-cli -p 6006 cluster myid # 3785af3f1f395e28a66a06e9c73305cbde59f1ba
可以使用reshard命令对数据进行重新分配
# reshard 后面 可以接集群中的任意节点
redis-cli -p 6000 --cluster reshard 127.0.0.1:6000
此时输入之前计算的数值 4096
接下来输入Node ID信息 3785af3f1f395e28a66a06e9c73305cbde59f1ba
数据从all节点进行分配,输入 all
如上 可以从日志看出数据分配的过程. 但是整个分配过程 是将16384个hash槽重新分配个已有的节点,相当于整个数据库的迁移工作,数据量大的情况下,可能会非常耗时,在生产环境中需要慎用
验证测试
# 重新输入命令 查看slot分配结果
redis-cli -p 6000 cluster slots
127.0.0.1:6001> set x2 world
-> Redirected to slot [6113] located at 127.0.0.1:6006
127.0.0.1:6001> get x2
-> Redirected to slot [6113] located at 127.0.0.1:6006
"world"
设置的key 已经被分配到新的6006节点上了。
删除节点
Redis Cluster 集群删除节点要求该节点的数据必须为空,否则不允许删除。
[ERR] Node 127.0.0.1:6006 is not empty! Reshard data away and try again.
因此,在删除节点之前必须转移数据,将待删除节点的数据迁移到其他节点中去
数据迁移
数据迁移的过程,其实也是reshard,只不过只需要指定特定的节点进行 数据转移,跟新增节点的数据分配过程差不多
# 输入reshard命令
redis-cli -p 6006 --cluster reshard 127.0.0.1:6006
数据转移到6001节点上去,接下来指定待删除的节点ID - 6006,可以指定多个来源,输入done结束
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1: f39bed78c36a901e703072df16b857f96939db2d
Source node #2: done
删除节点
redis-cli --cluster del-node 127.0.0.1:6000 f39bed78c36a901e703072df16b857f96939db2d
AndydeMacBook-Pro:node_6007 andy$ redis-cli --cluster del-node 127.0.0.1:6000 f39bed78c36a901e703072df16b857f96939db2d
>>> Removing node f39bed78c36a901e703072df16b857f96939db2d from cluster 127.0.0.1:6000
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
验证测试
节点的验证工作主要包含两方面:
-
节点的Key是否还存在
AndydeMacBook-Pro:node_6007 andy$ redis-cli -c -p 6000 127.0.0.1:6000> get x2 -> Redirected to slot [6113] located at 127.0.0.1:6001 "world" # 之前在6006节点设置的 x2 被成功的迁移到6001端口
-
查看集群状态
# 主节点删除后,6007从节点自动变成 1e160d4caa2f13ff7f9297861dc7303f9636f4a0 的副本,1e160d4caa2f13ff7f9297861dc7303f9636f4a0 为6001节点的Node id AndydeMacBook-Pro:node_6007 andy$ redis-cli --cluster check 127.0.0.1:6000 127.0.0.1:6000 (41f2d826...) -> 1 keys | 4096 slots | 1 slaves. 127.0.0.1:6001 (1e160d4c...) -> 2 keys | 8192 slots | 2 slaves. 127.0.0.1:6002 (b3065915...) -> 0 keys | 4096 slots | 1 slaves.
节点宕机
为了触发故障转移,验证Redis Cluster架构下的主从切换。我们可以把主节点的进程杀死,看从节点是否能正常切换。其次当节点重启后看其是否能正常加入集群。
数据现场
如上图,6003节点有2个从节点,分别为6000、6007
# x3 的 键值对 也存储在6003 节点上
AndydeMacBook-Pro:node_6007 andy$ redis-cli -c -p 6001
127.0.0.1:6001> get x3
-> Redirected to slot [1984] located at 127.0.0.1:6003
"world"
节点异常
# 人工杀掉 6003节点的进程ID
AndydeMacBook-Pro:redis-5.0.5 andy$ ps -ef | grep redis | grep 6003
501 6994 1 0 10:29上午 ?? 0:24.31 redis-server *:6003 [cluster]
AndydeMacBook-Pro:redis-5.0.5 andy$ kill -9 6994
验证检查
从上图看出6007节点升级为主节点,6000节点未副本节点。
# x3 数据也正常从6007节点查询
AndydeMacBook-Pro:node_6007 andy$ redis-cli -c -p 6001
127.0.0.1:6001> get x3
-> Redirected to slot [1984] located at 127.0.0.1:6007
"world"
重启6003Redis服务, 正常加入到Redis Cluster 集群