Contents

Docker部署Redis集群及集群伸缩

1. Docker部署Redis集群及集群伸缩

1.1. 创建6个data目录

1 mkdir /mnt/data/6381
2 mkdir /mnt/data/6382
3 mkdir /mnt/data/6383
4 mkdir /mnt/data/6384
5 mkdir /mnt/data/6385
6 mkdir /mnt/data/6386

1.2. 官网下载最新的redis包

1 wget http://download.redis.io/releases/redis-6.0.6.tar.gz

1.3. docker拉取对应的redis镜像

1 docker pull redis:6.0.6

1.4. 修改配置文件

1 [root@localhost ~]# cp redis-6.0.6/redis.conf /mnt/redis.conf
2 [root@localhost ~]# vim /mnt/redis.conf
3 # bind 127.0.0.1 "注释bind 127.0.0.1"
4 protected-mode no   #"将 protected-mode yes 改为 protected-mode no "
5 # daemonize yes  "注释daemonize yes, 或改为no"
6 cluster-enabled yes #"启用集群配置"
7 cluster-config-file nodes-6381.conf #"节点配置文件"
8 cluster-node-timeout 5000 # "节点通信超时时间5s"

1.5. 启动6台redis容器

1 docker run -p 6381:6379 --name redis01 -v /mnt/redis.conf:/etc/redis/redis.conf -v /mnt/data/6381:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
2 docker run -p 6382:6379 --name redis02 -v /mnt/redis.conf:/etc/redis/redis.conf -v /mnt/data/6382:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
3 docker run -p 6383:6379 --name redis03 -v /mnt/redis.conf:/etc/redis/redis.conf -v /mnt/data/6383:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
4 docker run -p 6384:6379 --name redis04 -v /mnt/redis.conf:/etc/redis/redis.conf -v /mnt/data/6384:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
5 docker run -p 6385:6379 --name redis05 -v /mnt/redis.conf:/etc/redis/redis.conf -v /mnt/data/6385:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
6 docker run -p 6386:6379 --name redis06 -v /mnt/redis.conf:/etc/redis/redis.conf -v /mnt/data/6386:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes

1.6. 查看各容器IP

 1 [root@localhost ~]# docker inspect redis01 | grep "172.17"
 2 172.172.0.2
 3 [root@localhost ~]# docker inspect redis02 | grep "172.17"
 4 172.172.0.3
 5 [root@localhost ~]# docker inspect redis03 | grep "172.17"
 6 172.172.0.4
 7 [root@localhost ~]# docker inspect redis04 | grep "172.17"
 8 172.172.0.5
 9 [root@localhost ~]# docker inspect redis05 | grep "172.17"
10 172.172.0.6
11 [root@localhost ~]# docker inspect redis06 | grep "172.17"
12 172.172.0.7

1.7. 进入任一容器配置集群(遇yes敲yes)

1 redis-cli --cluster create 172.17.0.2:6379 172.17.0.3:6379 172.17.0.4:6379 172.17.0.5:6379 172.17.0.6:6379 172.17.0.7:6379  --cluster-replicas 1

1.8. 查看集群信息

1 root@d5fb8214a10a:/data# cat nodes-6379.conf 
2 748eb947ae5ac0c721740870ad44cb356a4b0ca5 172.17.0.4:6379@16379 master - 0 1598101846000 3 connected 10923-16383
3 8e986c400c6b0d47064ee2fbf7a391574042dbc4 172.17.0.6:6379@16379 slave 092994cf7044995d41a876370af56c97894adea0 0 1598101846000 1 connected
4 df1c66d381237ed63a6a6045c84942b7a7f9df9 172.17.0.5:6379@16379 slave 748eb947ae5ac0c721740870ad44cb356a4b0ca5 0 1598101847085 3 connected
5 092994cf7044995d41a876370af56c97894adea0 172.17.0.2:6379@16379 myself,master - 0 1598101844000 1 connected 0-5460
6 220fba07c2e345c8aa4578e8bb3b45451377d335 172.17.0.7:6379@16379 slave bb02a3720ff638ea7edb147580e9ffa1dce29726 0 1598101845000 2 connected
7 bb02a3720ff638ea7edb147580e9ffa1dce29726 172.17.0.3:6379@16379 master - 0 1598101846077 2 connected 5461-10922
8 vars currentEpoch 6 lastVoteEpoch 0

1.9. 集群取存测试

1 172.17.0.2:6379>cluster nodes      # 查看本机信息
2 172.17.0.2:6379>cluster info       # 查看集群信息
3 172.17.0.2:6379>set lan golang     # master插入数据(可能会报错,叫我们去别的实例存)
4 172.17.0.3:6379>get lan            # node查询数据
5 (error) MOVED 5798 172.17.0.2:6379 # 告诉我们该数据在172.17.0.2上
6 172.17.0.5:6386> keys *            # 查键          
7 1) "lan"

解决(error) MOVED问题

连接时使用-c参数来启动集群模式,命令如下: redis-cli -c -p6381

1.10. 分片高可用测试(HA)

1docker stop redis03 #停止master3容器
2172.17.0.2:6379>cluster nodes       # 查看集群信息

/images/2023-10-03-001.png

docker start redis03 #恢复节点

/images/2023-10-03-002.png

1.11. 思考

如果6个容器分别在多台机上,使用172内网端如何解决该问题?

  • 解决思路
    • 方法1: 多态物理机配置成docker集群,etcd已确保了ip的唯一性。
    • 方法2: 集群中各个redis实例通过port+10000为集群通信端口,所有可以分别配置6个redis.conf的port端口分别为6381、6382、6383、6384、6385、6386,那么他们的集群通信端口为16382、16382、16383、16384、16385、16386;创建集群的时候使用真机ip+端口即可(如下)。
1 redis-cli --cluster create 192.168.1.1:6381 192.168.1.2:6382 192.168.1.3:6383 192.168.1.4:6384 192.168.1.5:6385 192.168.1.6:6386 --cluster-replicas 1

1.12. 集群存储原理

配置完集群后显示 hash slot的个数,每台机的slot范围=总数/主节点数,用户在任一台主节点上存储key值时,会将key值与CRC16进行相除,再与hash slot求余(%),余数落在哪个范围就存在哪台机上。

1.13. 集群扩容

  • 添加主节点
 1 !创建存储卷
 2 [root@localhost ~]# mkdir /mnt/data/6387
 3 !启动redis实例
 4 [root@localhost ~]# docker run -p 6387:6379 --name redis07 -v /mnt/redis.conf:/etc/redis/redis.conf -v /mnt/data/6387:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
 5 !进入redis01容器
 6 [root@localhost ~]# docker exec -it redis01 /bin/bash
 7 !添加到集群
 8 root@da8d8sew8486a# redis-cli --cluster add-node 172.17.0.8:6379 172.17.0.3:6379
 9 !获取新节点ID
10 root@da8d8sew8486a# redis-cli --cluster check 172.17.0.8:6379 | grep 0.8:6379$ |awk '{print $2}'
11 37becf5c7faca5986a313c95bc23f5ab8c547210 
12 !重新分配哈希槽,一共16384/4=4096(4个主节点)
13 root@da8d8sew8486a# redis-cli --cluster reshard 172.17.0.3:6379
14 第一个填4096
15 第二个填新节点ID
16 第三个填all
17 第四个填yes
18 !检查集群
19 root@da8d8sew8486a# redis-cli --cluster check 172.17.0.8:6379 
  • 添加从节点
1 !创建存储卷
2 [root@localhost ~]# mkdir /mnt/data/6388
3 !启动redis实例
4 [root@localhost ~]# docker run -p 6388:6379 --name redis08 -v /mnt/redis.conf:/etc/redis/redis.conf -v /mnt/data/6388:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
5 !进入redis01容器
6 [root@localhost ~]# docker exec -it redis01 /bin/bash
7 !添加到集群(两种方式,指定给谁添加[--master-id]或者自动为最少salve的主节点添加)
8 root@da8d8sew8486a# redis-cli --cluster add-node --cluster-slave 172.17.0.9:6379 172.17.0.3:6379

1.14. 集群缩容

  • 删除从节点
1 redis-cli --cluster del-node IP:端口 ID
  • 删除主节点
1 !重新分片
2 redis-cli --cluster reshard 172.17.0.8:6379
3 第一个填4096(表示要迁移的哈希槽)
4 第二个填任一master(表示把哈希槽给谁)
5 第三个填要移除的master ID
6 第四个填要移除的master ID2,没有的话填done
7 第五个填yes(表示确认修改)
8 !移除节点(跟移除从节点一样)
9 redis-cli --cluster del-node 172.17.0.8:6379 
8 c18466f6ab920e459267f878ec71f0f19016015

市面上K8s部署redis集群都是通过第三台机来手动配置集群,每次扩缩容都需要人工操作。