项目中用到了Redis, 所以打算用Docker在本地搭建一个Redis集群. 搭建时用到了docker-compose, 而网上大多数参考都是先搭建六个单节点, 然后再创建主从节点, 在这种方式下没办法细粒度的指定哪个节点为主节点, 哪个节点为指定主节点的从节点(其实可以, 但是很麻烦)
所以在docker-compose.yml中增加了配置, 完成了一条命令创建三主三从的Redis节点, 并且可以根据需求来指定哪些为主, 哪些为从, 以及从节点属于哪个主节点
使用Docker部署Redis集群-三主三从
本案例源代码: https://github.com/JasonkayZK/ttmall/tree/master/docker/redis-cluster
拉取镜像
本次使用的是Redis最新的镜像版本: Redis:5.0.7
创建集群网络
使用命令创建redis集群的网络redis-cluster-net:
1
| docker network create --subnet=192.168.200.0/24 redis-cluster-net
|
说明:
① 创建一个网段: 192.168.200.0(docker默认使用172.17.0.1网段)
② 24表示子网掩码有24位,即255.255.255.0
集群ip以及端口安排:
| ip |
port |
remark |
| 192.168.200.11 |
7001 |
主节点: master-1 |
| 192.168.200.12 |
7002 |
主节点: master-2 |
| 192.168.200.13 |
7003 |
主节点: master-3 |
| 192.168.200.14 |
7004 |
从节点: slave-1 |
| 192.168.200.15 |
7005 |
从节点: slave-2 |
| 192.168.200.16 |
7006 |
从节点: slave-3 |
创建redis.conf配置文件
这里分别给出一个主节点和一个从节点的最小配置文件例子, 其他的修改一些端口号即可
主节点
redis-7001.conf
1 2 3 4 5 6 7 8
| port 7001 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes daemonize no protected-mode no pidfile /var/run/redis_7001.pid
|
从节点
redis-7004.conf
1 2 3 4 5 6 7
| port 7004 cluster-enabled no appendonly yes daemonize no protected-mode no pidfile /var/run/redis_7004.pid slaveof 192.168.1.103 7001
|
说明:
主节点主要配置说明:
- port: 指定了启动的端口号
- cluster-enabled: 启动允许集群
- cluster-config-file & cluster-node-timeout: 集群配置文件(自动创建)和集群超时时间
- appendonly: 持久化 yes
- daemonize: 后台运行 no
- protected-mode: 允许外部IP访问
主节点配置注意事项:
① 开启持久化后默认的数据路径在容器的/data下
② daemonize一定要关闭, 否则容器启动后会因为没有前台线程而直接关闭
从节点主要配置说明:
- cluster-enabled: no 不参与集群分配
- appendonly: 持久化 yes
- daemonize: 后台运行 no(理由同上)
- slaveof 192.168.1.103 7001: 直接指定成为对应master的从节点
从节点配置注意事项:
① cluster-enabled配置为no, 不参与集群分配, 否则将无法直接指定slaveof
② 从节点也进行持久化, 其实可以主节点持久化, 从节点做流量访问, 否则有可能影响性能
③ slaveof ip port直接指定了本节点是指定节点一个从节点(注意ip port中间是空格而不是冒号)
其他相关节点的配置与上面类似, 修改port即可
源代码见: https://github.com/JasonkayZK/ttmall/tree/master/docker/redis-cluster
更详细配置说明见: 转-redis常用配置redis-conf说明
创建docker-compose.yml
docker-compose.yml中主要完成镜像, 网络等声明以及各个容器的内容等, 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| version: '3.7'
x-image: &default-image redis:5.0.7
networks: redis-cluster-net: external: name: redis-cluster-net
services: redis-master-1: image: *default-image container_name: redis-master-1 command: ["redis-server", "/home/redis/cluster/redis.conf"] networks: redis-cluster-net: ipv4_address: 192.168.200.11 volumes: - ./redis-7001.conf:/home/redis/cluster/redis.conf - ./7001/data:/data ports: - 7001:7001 - 17001:17001
redis-master-2: image: *default-image container_name: redis-master-2 command: ["redis-server", "/home/redis/cluster/redis.conf"] networks: redis-cluster-net: ipv4_address: 192.168.200.12 volumes: - ./redis-7002.conf:/home/redis/cluster/redis.conf - ./7002/data:/data ports: - 7002:7002 - 17002:17002
redis-master-3: image: *default-image container_name: redis-master-3 command: ["redis-server", "/home/redis/cluster/redis.conf"] networks: redis-cluster-net: ipv4_address: 192.168.200.13 volumes: - ./redis-7003.conf:/home/redis/cluster/redis.conf - ./7003/data:/data ports: - 7003:7003 - 17003:17003
redis-salve-1: image: *default-image container_name: redis-salve-1 command: ["redis-server", "/home/redis/cluster/redis.conf"] networks: redis-cluster-net: ipv4_address: 192.168.200.14 volumes: - ./redis-7004.conf:/home/redis/cluster/redis.conf - ./7004/data:/data ports: - 7004:7004 - 17004:17004
redis-salve-2: image: *default-image container_name: redis-salve-2 command: ["redis-server", "/home/redis/cluster/redis.conf"] networks: redis-cluster-net: ipv4_address: 192.168.200.15 volumes: - ./redis-7005.conf:/home/redis/cluster/redis.conf - ./7005/data:/data ports: - 7005:7005 - 17005:17005
redis-salve-3: image: *default-image container_name: redis-salve-3 command: ["redis-server", "/home/redis/cluster/redis.conf"] networks: redis-cluster-net: ipv4_address: 192.168.200.16 volumes: - ./redis-7006.conf:/home/redis/cluster/redis.conf - ./7006/data:/data ports: - 7006:7006 - 17006:17006
|
说明:
- docker-compose的版本为最新版: 3.7, 如果你的docker版本较低, 可以修改为更低的版本(并没有用新特性, 兼容低版本)
- 配置指定了使用的镜像, 容器名称, 创建的网络, 文件映射, 端口映射等
- volumes分别将本地配置和持久化数据进行映射
- ports分别将节点端口和集群端口映射到本地(port+10000)
启动
在docker-compose.yml所在目录执行命令:
1 2 3 4 5 6 7
| $ docker-compose up -d Creating redis-master-3 ... done Creating redis-salve-3 ... done Creating redis-salve-1 ... done Creating redis-master-2 ... done Creating redis-master-1 ... done Creating redis-salve-2 ... done
|
即创建了六个Redis示例
注意: 此时仅仅创建了三对主从节点, 但是三个主节点(7001, 7002, 7003)是孤立的, 并且还未分配slots
创建集群并进行slots分配
进入任一主节点(注意是主节点), 并执行下面的命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| root@141307f0c6e2:/data# redis-cli --cluster create 192.168.1.103:7001 192.168.1.103:7002 192.168.1.103:7003 --cluster-replicas 0 >>> Performing hash slots allocation on 3 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 M: 2056e77f1e6d24800e7af83770b5b92ac3091958 192.168.1.103:7001 slots:[0-5460] (5461 slots) master M: 56908abced57c7ed2ca0a22c0265a8b8ba5056e8 192.168.1.103:7002 slots:[5461-10922] (5462 slots) master M: 06f0cb6f92770709d8afdc226da16abc6ab3679d 192.168.1.103:7003 slots:[10923-16383] (5461 slots) master Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join .. >>> Performing Cluster Check (using node 192.168.1.103:7001) M: 2056e77f1e6d24800e7af83770b5b92ac3091958 192.168.1.103:7001 slots:[0-5460] (5461 slots) master M: 56908abced57c7ed2ca0a22c0265a8b8ba5056e8 192.168.200.1:7002 slots:[5461-10922] (5462 slots) master M: 06f0cb6f92770709d8afdc226da16abc6ab3679d 192.168.200.1:7003 slots:[10923-16383] (5461 slots) master [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
|
输入yes同意slots分配即可完成集群创建
测试
在7001(master-1)中添加几个k-v对:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 7001(127.0.0.1:7001)>set hello world "OK" 7001(127.0.0.1:7001)>set hello1 world1 已连接到集群。 7001(127.0.0.1:7001)> 7001(192.168.200.1:7003)> "OK" 7001(192.168.200.1:7003)>set hello2 world2 已连接到集群。 7001(192.168.200.1:7003)> 7001(192.168.200.1:7002)> "OK" 7001(192.168.200.1:7002)>
|
说明: 此时由于redis分配规则, 某些key值在计算完hash后会被分配到其他master节点(如上)
在这种情况下, 理论上在master-1的从节点上应当是无法查询到其他加入到其他主节点中的key的
执行命令:
1 2 3 4 5 6
| 7004:0>get hello "world" 7004:0>get hello1 null 7004:0>get hello2 null
|
可见查询hello1, hello2均为null, 而查询其他从节点可查到对应数据
1 2
| 7005:0>get hello2 "world2"
|
说明确实完成了主从复制, 集群搭建成功!
集群关闭
在docker-compose.yml目录下执行下述命令即可关闭:
注意:
使用docker-compose up -d命令创建的容器会在down了之后自动删除!
而再次启动时, 如果指定的数据路径存在数据, 则无法创建集群
所以重新创建redis集群需要:
- 将每个节点下aof、rdb、nodes.conf本地备份文件删除
- 127.0.0.1:7001> flushdb #清空当前数据库(这一步可以省略)
- 重新执行创建集群命令
具体可见: 重新创建redis集群的注意事项
参考文章