§1 镜像
docker pull redis:6.0.8
§2 主机目录
目录层级遵循
${prefix}/cluster/host/xx
如:
- /docker/redis/cluster_01/master_01/conf
- /docker/redis/cluster_01/master_01/data
- /docker/redis/cluster_01/slave_01/conf
- /docker/redis/cluster_01/slave_01/data
§3 集群部署
启动
docker run -d --privileged=true \
--name redis-node-01 --net host \
-v /docker/redis/cluster_01/node_01/data:/data \
redis:6.0.8 \
--cluster-enabled yes --appendonly yes --port 6381
docker run -d --privileged=true \
--name redis-node-02 --net host \
-v /docker/redis/cluster_01/node_02/data:/data \
redis:6.0.8 \
--cluster-enabled yes --appendonly yes --port 6382
docker run -d --privileged=true \
--name redis-node-03 --net host \
-v /docker/redis/cluster_01/node_03/data:/data \
redis:6.0.8 \
--cluster-enabled yes --appendonly yes --port 6383
docker run -d --privileged=true \
--name redis-node-04 --net host \
-v /docker/redis/cluster_01/node_04/data:/data \
redis:6.0.8 \
--cluster-enabled yes --appendonly yes --port 6384
docker run -d --privileged=true \
--name redis-node-05 --net host \
-v /docker/redis/cluster_01/node_05/data:/data \
redis:6.0.8 \
--cluster-enabled yes --appendonly yes --port 6385
docker run -d --privileged=true \
--name redis-node-06 --net host \
-v /docker/redis/cluster_01/node_06/data:/data \
redis:6.0.8 \
--cluster-enabled yes --appendonly yes --port 6386
参数说明
-
-d
redis 作为服务后台运行 -
–name
redis 节点名字 -
net host
容器网络模式,使用宿主机 IP 和端口
此模式下不能使用 -p 或 -P 指定端口
否则会出现下面警告,配置也不会生效Published ports are discarded when using host network mode
-
–privileged=true
获取宿主机 root 权限 -
-v
添加数据卷挂载 -
–cluster-enabled
开启 redis 集群 -
appendonly yes
开启 redis 持久化 -
–port
指定 redis 节点的端口
配合 -net host 指定端口
主从配置
任选一个 docker 节点,进入容器,通过下面 reids-cli 配置集群
redis-cli --cluster create 192.168.3.11:6381 192.168.3.11:6382 192.168.3.11:6383 192.168.3.11:6384 192.168.3.11:6385 192.168.3.11:6386 --cluster-replicas 1
参数说明
- –cluster create
集群中所有 redis 节点的 ip 端口 - –cluster-replicas
集群中备份数量
相当于附属每个 master 的 slave 的数量
集群配置效果如下图
hash 槽 相关说明见连接
注意 这里有一步确认,需要输入后看到下图红框才算成功
注意
-
node is not empty
[ERR] Node 192.168.3.11:6381 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
说明对应节点的存储位置下有数据,需要删除或移动。
按上面示例的配置搭建时,可以使用下面指令清理rm -rf /docker/redis/cluster_01
-
redis-cli --cluster create 时,cluster node 列表务必核对清楚,否则容易莫名其妙少一个节点
-
redis-cli --cluster create 时,中间有一步交互确认,需要键入 yes,否则集群搭建不起来
-
(error) MOVED
(error) MOVED 15495 192.168.3.11:6383
集群模式下,登录 redis-cli 需要添加 -c 参数,如下所示
redis-cli -c -p 6381
因为 redis 依赖 hash 槽,对 key 进行操作时会先计算 hash 槽,并移动到此 hash 对应的节点上
示例中报错信息里的 15495 即 hash 槽位,192.168.3.11:6383 即对应节点
没有 -c 参数会使移动失败,因此报错
§4 集群容错和扩容缩容
§4.1 容错
参考上面示例中 redis-cli --cluster ckeck 的输出,此时 redis 集群的结构如下图所示
在上面集群中
- 若一个 master 挂了,如 6381,则其 slave(即 6385) 顶替其为 master,且持有与原 master 一致的数据
- 若挂掉的 master 复活,则已经顶替为 master 的 slave 身份不变,复活的 master 身份变为 slave
§4.2 扩容
运行新 redis nodes
docker run -d --privileged=true \
--name redis-node-07 --net host \
-v /docker/redis/cluster_01/node_07/data:/data \
redis:6.0.8 \
--cluster-enabled yes --appendonly yes --port 6387
docker run -d --privileged=true \
--name redis-node-08 --net host \
-v /docker/redis/cluster_01/node_08/data:/data \
redis:6.0.8 \
--cluster-enabled yes --appendonly yes --port 6388
进入新节点容器,分别以主从身份将新节点加入集群
docker exec -it 129eb34dcf09 /bin/bash
redis-cli --cluster add-node 192.168.3.11:6387 192.168.3.11:6381
exit
docker exec -it 15e47f2a1bb5 /bin/bash
redis-cli --cluster add-node 192.168.3.11:6388 192.168.3.11:6381 --cluster-slave --cluster-master-id 14b47d80f327d499820def9bdf286c498f03f653
exit
==任意容器中查看集群状态 ==
redis-cli --cluster check 192.168.3.11:6381
重新分配 hash 槽
此时无法使用 redis-cli --cluster rebalance 重新分配 hash 槽,因为所有节点的 hash 槽占用率都很低
因此使用 redis-cli --cluster reshard 命令
说明:
- 可以使用任意集群中的节点进行 hash 槽的重分配
- 第一步需要确认分配 hash 槽的数量
通常 16384 / 集群中master个数 即可 - 第二步输入接受 hash 槽的 node 的 id
- 第三步确认 hash 槽来源,
- 输入 all:示例中选择
可以从所有有 hash 槽的 master 节点均匀让渡 hash 槽给新节点,其他节点均分第一步填写的数值 - 输入 node-id-1、回车、node-id-2、回车……、done:
从键入的 id 的节点让渡第一步填写的数值的 hash 槽给新节点
可以精准控制每个节点让渡多少 hash 槽给新节点,但通常需要依次对每个原有节点进行操作以完成整个分配过程
也可以一次输入多个节点,也可以使输入 id 的节点均分第一步中填写的数值
- 输入 all:示例中选择
- 第四步是一个确认,询问是否按分析的结果执行分配,输入 yes 即可
使用下面指令查询分配结果
redis-cli --cluster check 192.168.3.11:6381
可以看到现在是 4 个 master 均分所有 hash 槽,
且每个扩容前的节点在自己的 hash 槽区间上从开头(左侧)截取所需数量的 hash 槽进行让渡
新节点(6387) 持有的 hash 槽由 3 个区间段组成
§4.3 缩容
以移除集群中 6387/6388 两个节点为例
重新分配 hash 槽
root@msi-linux7:/data# redis-cli --cluster reshard 192.168.3.11:6381
说明:
-
可以使用任意集群中的节点进行 hash 槽的重分配
-
第一步需要确认分配 hash 槽的数量
示例中是重新分配待移除节点上的所有 hash 槽 -
第二步输入接受 hash 槽的 node 的 id
示例中为了演示方便都用 6381 节点接受
也可以分多次分配 -
第三步确认 hash 槽来源,
要移除 6387 上的 hash 槽,所以填写 6387 的 node id
然后输入 done 完成 -
第四步是一个确认,询问是否按分析的结果执行分配,输入 yes 即可
检查重新分配结果
redis-cli --cluster check 192.168.3.11:6381
可见待删除的节点 6387 已经没有 hash 槽了
同时,原本 6387 的 slave 已经过继给了 6381
删除节点
redis-cli --cluster del-node 192.168.3.11:6381 14b47d80f327d499820def9bdf286c498f03f653
redis-cli --cluster del-node 192.168.3.11:6381 886f415bc4d296a7d8794a88f47e7e9f35f7a2a9
如果有需要,可以重新分配 hash 槽,使三个节点负载均衡
或者在一开始分配时,就考虑此问题
重分配 hash 槽和节点删除的顺序问题
有些教程和帖子上的顺序为
- 删除从节点 6388
- 重分配 hash 槽
- 删除主节点 6387
因作者实践经验有限,不能验证,但考虑
若先删除从节点,在 hash 槽重分配完成前,主节点 6387 挂了的情况时可能存在问题
因此此贴中的顺序是先重新分配 hash 槽