Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 的 NoSQL 数据库,并提供多种语言的 API。
大型网站为了提高站点响应速度,使用缓存工具将热点数据保存在内存中,避免直接从后端数据库读取查询,降低后端压力,其中常见的 Cache 工具有 Memcached 和 Redis。
Memcached 更侧重于⾼性能内存/缓存系统,⽽ Redis 则⽀持持久化,主打数据库功能,兼可作缓存系统(性能也很⾼)。如果业务中更加侧重性能的⾼效性,对持久化要求不⾼,那么应该优先选择 Memcached。如果业务中对持久化有需求或者对数据涉及到存储、排序等一系列复杂的操作,比如业务中有排⾏榜类应⽤、社交关系存储、数据排重、实时配置等功能,那么应该优先选择 Redis。
在大型站点应用中,热点数据几十 ~ 上百 G 很普遍,而无论是物理机、云主机(虚拟机),内存资源往往是有限的,虽然目前硬件成本降低,几十 G 几十核的主机也很常见,但是对于 Redis 这种工作进程为单线程模式的工具来说,一台主机只运行一个实例就有些浪费,且出现单点故障时影响范围很大。同时,Redis 管理大内存时不如管理相对较小的内存高效,据第三方测试,Redis 单进程内存分配达到 20G 后性能急剧下降,因此普遍使用的方式为单进程分配 8G 内存,单主机开启多个 Redis Instance.
Redis 三种集群方式:主从复制、哨兵模式(Sentinel)、Cluster 集群。
主从复制:
从服务器将向主服务器发送 SYNC 命令,接收到 SYNC 命令后的主服务器会进行一次 BGSAVE 命令,在执行期间,会将所有命令写入缓冲区中,当 BGSAVE 命令执行完毕之后会将生成的 RDB 文件发送给从服务器,从服务器使用这个文件加载数据到内存中,之后主服务器会以 Redis 命令协议的格式将缓冲区的命令发送给从服务器。
此后每次主服务执行命令都会同步给从服务器,即使有多个从服务器向主服务器发送 SYNC 命令,主服务器也只会执行一个 BGSAVE 命令,就可以处理接下来的同步请求。一个主服务器可以拥有多个从服务器,而从服务器也可拥有从服务器,复制功能不会阻塞主服务器,即使有一个或多个同步请求,主服务器依然能处理命令请求。
当配置了主从复制模式时需要开启主服务器的持久化功能,如果将主服务器的持久化功能关闭,主服务器一旦重启,所有从服务器的数据将会丢失,即使配置了 Sentinel 模式,如果主服务器自动拉起进程比较快,以至于在 Sentinel 模式下还未选举出新的主服务器,主服务的启动也会造成子服务器的数据丢失。
哨兵模式:
Redis 的 Sentinel 系统用于管理多个 Redis,主要执行以下三件事:
(1) 监控:Sentinel 会不断的检查主从服务器运行状态;
(2) 提醒:当某个 Redis 服务器出现故障,可通过 API 或者其他应用程序发送通知;
(3) 自动故障迁移:当一个主服务器不能正常工作时,Sentinel 会进行一次故障自动迁移,会将失效主服务器的从服务器选举出一个新的主服务器,剩下的从服务器将会自动连接复制选举出来的新服务器的数据;
Redis 的 Sentinel 系统是一个分布式的系统,可以在系统中配置一个或多个 Sentinel。
当一个 Sentinel 发现主服务器下线时,称为主观下线,只有多个 Sentinel 都发现主服务下线,并相互之间通过命令进行交流判断主服务器下线时,称为客观下线。只有对主服务器进行客观下线时,会选举出领头 Sentinel,选举出之后,会进行新的主服务器投票选举,选举出一个从服务器升级为主服务器。并向被选中的从服务器发送 SLAVEOF no one 命令,让其变为主服务器,通过发布订阅的功能,将新的配置广播给其他 Sentinel 进行更新,并向下线的主服务器发送 SLAVEOF 命令,让其复制新的主服务器,当所有从服务器都已经开始复制新的主服务器时,领头 Sentinel 终止本次故障迁移。
当一个 Redis 实例被重新配置是,无论是被设置成主服务器、从服务器、又或者被设置成其他主服务器的从服务器 ,Sentinel 都会向被重新配置的实例发送一个 CONFIG REWRITE 命令, 从而确保这些配置会持久化在硬盘里。
Redis cluster:
主从复制和哨兵模式都难以在线扩容,而 Redis cluster 集群实现了对 Redis 的水平扩容,即启动 N 个Redis 节点,每个节点又可以有自己的从服务器,将数据均匀分布的存储在这 N 个结点上,每个节点存储数据的 1/N。Redis cluster 集群就是一个可以在多个 Redis 节点之间进行数据共享的设施;Redis cluster 集群采用的是无中心化配置,即节点 A 无法处理,会将请求转发至节点 B 进行处理。
Redis 集群中的键空间被分割为 16384 个槽位。每个主节点负责 16384 中槽位的一部分,Redis 使用CRC16 算法进行槽位分配。为了保证高可用,cluster 模式也引入了主从复制模式,一个主节点对应一个或多个从节点,当主节点发生宕机时,可进行故障转移,将子节点升级为主节点。
本文部署 3 个 Redis 节点,来演示主从复制和哨兵模式,部署 6 个节点(至少 6 个节点),来演示 Cluster 集群。
1. 部署环境
IP 地址(本地测试环境):192.168.0.10
操作系统:Linux CentOS 7.9
Docker 版本: 20.10.7
Docker Compose 版本: 2.6.1
Redis 集群目录:/home/docker/redis_cluster
2. Redis 集群目录
在 /home/docker/redis_cluster 目录下,目录结构如下:
redis_cluster |- master | |- conf | | |- redis.cnf | | | |- data | |- log | |- node_1 | |- conf | | |- redis.cnf | | | |- data | |- log | |- node_2 | |- conf | | |- redis.cnf | | | |- data | |- log | | ... | |- scripts | |- run_redis_server.sh | |- replication | |- docker-compose.yml | |- sentinel | |- conf_1 | | |- sentinel.cnf | |- conf_2 | | |- sentinel.cnf | |- conf_3 | | |- sentinel.cnf | | | | ... | | | |- docker-compose.yml | |- cluster | |- docker-compose.yml | |- common.env
3. 配置文件
1) 创建 master 的 redis.conf 文件
在 /home/docker/redis_cluster/master/conf 目录下,创建 redis.conf 文件,内容如下:
bind 0.0.0.0 port 6379 protected-mode no slave-read-only no logfile /var/log/redis.log #dir /data
2) 创建 node_1 的 redis.conf 文件
在 /home/docker/redis_cluster/node_1/conf 目录下,创建 redis.conf 文件,内容如下:
bind 0.0.0.0 port 6380 protected-mode no slave-read-only no logfile /var/log/redis.log #dir /data
3) 创建 node_2 的 redis.conf 文件
在 /home/docker/redis_cluster/node_2/conf 目录下,创建 redis.conf 文件,内容如下:
bind 0.0.0.0 port 6381 protected-mode no slave-read-only no logfile /var/log/redis.log #dir /data
4) 创建 common.env 文件
在 /home/docker/redis_cluster 目录下,创建 common.env 文件,内容如下:
REQUIRE_PASS=123456 MASTER_AUTH=123456 MASTER_HOST=redis_master MASTER_PORT=6379
5) 创建 run_redis_server.sh 文件
在 /home/docker/redis_cluster/scripts 目录下,创建 run_redis_server.sh 文件,内容如下: #!/bin/bash if [[ $1 = 'master' ]]; then redis-server /etc/redis/redis.conf --requirepass $REQUIRE_PASS --masterauth $MASTER_AUTH elif [[ $1 = 'slave' ]]; then redis-server /etc/redis/redis.conf --slaveof $MASTER_HOST $MASTER_PORT --requirepass $REQUIRE_PASS --masterauth $MASTER_AUTH else echo "Usage: $0 [master|slave]" echo " master - Redis master" echo " slave - Redis slave" fi
4. 主从复制 (Replication)
1) 创建 docker-compose.yml
在 /home/docker/redis_cluster/replication 目录下,创建 docker-compose.yml 文件,内容如下:
version: "3" services: redis_master: image: redis:6 container_name: redis_master volumes: - /home/docker/redis_cluster/master/data:/data - /home/docker/redis_cluster/master/conf:/etc/redis - /home/docker/redis_cluster/master/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.10 command: /bin/bash /root/redis_scripts/run_redis_server.sh master env_file: - /home/docker/redis_cluster/common.env redis_node_1: image: redis:6 container_name: redis_node_1 depends_on: - redis_master volumes: - /home/docker/redis_cluster/node_1/data:/data - /home/docker/redis_cluster/node_1/conf:/etc/redis - /home/docker/redis_cluster/node_1/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.11 command: /bin/bash /root/redis_scripts/run_redis_server.sh slave env_file: - /home/docker/redis_cluster/common.env redis_node_2: image: redis:6 container_name: redis_node_2 depends_on: - redis_master volumes: - /home/docker/redis_cluster/node_2/data:/data - /home/docker/redis_cluster/node_2/conf:/etc/redis - /home/docker/redis_cluster/node_2/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.12 command: /bin/bash /root/redis_scripts/run_redis_server.sh slave env_file: - /home/docker/redis_cluster/common.env networks: my_net: driver: bridge ipam: config: - subnet: 172.25.0.0/16
2) 启动
$ cd /home/docker/redis_cluster/replication
$ docker-compose up -d # 在后台运行
[+] Running 4/4 ⠿ Network redis_cluster_my_net Created 0.0s ⠿ Container redis_node_1 Started 0.6s ⠿ Container redis_node_2 Started 0.6s ⠿ Container redis_master Started 0.6s
注:本地 docker 没有所需要的镜像时,会自动下载所需的镜像。遇到无法自动下载的情况,可以使用 docker pull 命令下载所需的镜像,再运行 docker-compose up 命令。
$ docker images # 查看镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
redis 6 136fbb04568e 7 days ago 113MB
$ docker ps
CONTAINER ID IMAGE COMMAND ... PORTS NAMES 06ea72a37b5f redis:6 "docker-entrypoint.s…" 6379/tcp redis_master e9db204dfced redis:6 "docker-entrypoint.s…" 6379/tcp redis_node_2 d150fd52bf13 redis:6 "docker-entrypoint.s…" 6379/tcp redis_node_1
$ docker exec -it redis_master /bin/bash # 进入 redis_master 容器
root@a762d02ea05f:/data# redis-cli -p 6379 127.0.0.1:6379> auth 123456 OK 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=172.25.0.11,port=6380,state=online,offset=4858,lag=1 slave1:ip=172.25.0.12,port=6381,state=online,offset=4858,lag=1 master_failover_state:no-failover master_replid:d5971ebdc023fdbeff153f84b51c047744db6456 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:4858 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:4858
5. 哨兵模式 (Sentinel)
1) 创建 Sentinel 配置文件
在 /home/docker/redis_cluster/sentinel/conf_1 目录下,创建 sentinel.conf 文件,内容如下:
port 26379 dir /tmp sentinel monitor the_master 172.25.0.10 6379 2 sentinel auth-pass the_master 123456 sentinel down-after-milliseconds the_master 30000 sentinel parallel-syncs the_master 1 sentinel failover-timeout the_master 10000 sentinel deny-scripts-reconfig yes
在 /home/docker/redis_cluster/sentinel/conf_2 目录下,创建 sentinel.conf 文件,内容如下:
port 26380 dir /tmp sentinel monitor the_master 172.25.0.10 6379 2 sentinel auth-pass the_master 123456 sentinel down-after-milliseconds the_master 30000 sentinel parallel-syncs the_master 1 sentinel failover-timeout the_master 10000 sentinel deny-scripts-reconfig yes
在 /home/docker/redis_cluster/sentinel/conf_3 目录下,创建 sentinel.conf 文件,内容如下:
port 26381 dir /tmp sentinel monitor the_master 172.25.0.10 6379 2 sentinel auth-pass the_master 123456 sentinel down-after-milliseconds the_master 30000 sentinel parallel-syncs the_master 1 sentinel failover-timeout the_master 10000 sentinel deny-scripts-reconfig yes
2) 创建 docker-compose.yml
在 /home/docker/redis_cluster/sentinel 目录下,创建 docker-compose.yml 文件,内容如下:
version: "3" services: redis_master: image: redis:6 container_name: redis_master volumes: - /home/docker/redis_cluster/master/data:/data - /home/docker/redis_cluster/master/conf:/etc/redis - /home/docker/redis_cluster/master/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.10 command: /bin/bash /root/redis_scripts/run_redis_server.sh master env_file: - /home/docker/redis_cluster/common.env redis_node_1: image: redis:6 container_name: redis_node_1 depends_on: - redis_master volumes: - /home/docker/redis_cluster/node_1/data:/data - /home/docker/redis_cluster/node_1/conf:/etc/redis - /home/docker/redis_cluster/node_1/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.11 command: /bin/bash /root/redis_scripts/run_redis_server.sh slave env_file: - /home/docker/redis_cluster/common.env redis_node_2: image: redis:6 container_name: redis_node_2 depends_on: - redis_master volumes: - /home/docker/redis_cluster/node_2/data:/data - /home/docker/redis_cluster/node_2/conf:/etc/redis - /home/docker/redis_cluster/node_2/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.12 command: /bin/bash /root/redis_scripts/run_redis_server.sh slave env_file: - /home/docker/redis_cluster/common.env sentinel_1: image: redis:6 container_name: redis_sentinel_1 depends_on: - redis_master - redis_node_1 - redis_node_2 volumes: - /home/docker/redis_cluster/sentinel/conf_1:/usr/local/etc/redis networks: my_net: ipv4_address: 172.25.0.13 command: redis-sentinel /usr/local/etc/redis/sentinel.conf sentinel_2: image: redis:6 container_name: redis_sentinel_2 depends_on: - redis_master - redis_node_1 - redis_node_2 volumes: - /home/docker/redis_cluster/sentinel/conf_2:/usr/local/etc/redis networks: my_net: ipv4_address: 172.25.0.14 command: redis-sentinel /usr/local/etc/redis/sentinel.conf sentinel_3: image: redis:6 container_name: redis_sentinel_3 depends_on: - redis_master - redis_node_1 - redis_node_2 volumes: - /home/docker/redis_cluster/sentinel/conf_3:/usr/local/etc/redis networks: my_net: ipv4_address: 172.25.0.15 command: redis-sentinel /usr/local/etc/redis/sentinel.conf networks: my_net: driver: bridge ipam: config: - subnet: 172.25.0.0/16
3) 启动
$ cd /home/docker/redis_cluster/sentinel
$ docker-compose up
[+] Running 7/7r sentinel]# docker-compose up ⠿ Network sentinel_my_net Created 0.0s ⠿ Container redis_master Created 0.0s ⠿ Container redis_node_2 Created 0.0s ⠿ Container redis_node_1 Created 0.0s ⠿ Container redis_sentinel_1 Created 0.0s ⠿ Container redis_sentinel_2 Created 0.0s ⠿ Container redis_sentinel_3 Created 0.0s Attaching to redis_master, redis_node_1, redis_node_2, redis_sentinel_1, redis_sentinel_2, redis_sentinel_3 ... redis_sentinel_1 | 1:X 13 Oct 2022 10:12:52.996 # Sentinel ID is 141d777f9984c5aa5f5e6f82fd6d9dc9e865c51d redis_sentinel_1 | 1:X 13 Oct 2022 10:12:52.996 # +monitor master the_master 172.25.0.10 6379 quorum 2 ... redis_sentinel_2 | 1:X 13 Oct 2022 10:12:53.146 # Sentinel ID is a1df19e38db034efd18add95b7bbcf6bbc6000d5 redis_sentinel_2 | 1:X 13 Oct 2022 10:12:53.146 # +monitor master the_master 172.25.0.10 6379 quorum 2 ... redis_sentinel_3 | 1:X 13 Oct 2022 10:12:53.203 # Sentinel ID is 6ba1b24f82a3e53d7fcb1e3ff9f51292c4c24440 redis_sentinel_3 | 1:X 13 Oct 2022 10:12:53.203 # +monitor master the_master 172.25.0.10 6379 quorum 2
注:如果之前 /home/docker/redis_cluster/replication 目录下运行的 docker-compose up 还在运行,需要先回到 /home/docker/redis_cluster/replication 目录下运行 docker-compose down。
控制台(Console 1)处于阻塞状态,redis_sentinel_1、redis_sentinel_2 和 redis_sentinel_3 监控 master 的状态。
4) 模拟 master 节点故障
可以暂停 redis_master 的容器,打开一个新的控制台(Console 2):
$ docker pause redis_master
以上命令运行后,控制台(Console 1)阻塞状态结束阻塞,新显示内容如下:
... redis_node_1 | 9:S 13 Oct 2022 10:14:34.075 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization. redis_sentinel_2 | 1:X 13 Oct 2022 10:14:34.965 * +slave-reconf-inprog slave 172.25.0.11:6380 172.25.0.11 6380 @ the_master 172.25.0.10 6379 redis_sentinel_2 | 1:X 13 Oct 2022 10:14:34.965 * +slave-reconf-done slave 172.25.0.11:6380 172.25.0.11 6380 @ the_master 172.25.0.10 6379 redis_sentinel_2 | 1:X 13 Oct 2022 10:14:35.055 # -odown master the_master 172.25.0.10 6379 redis_sentinel_2 | 1:X 13 Oct 2022 10:14:35.055 # +failover-end master the_master 172.25.0.10 6379 redis_sentinel_2 | 1:X 13 Oct 2022 10:14:35.055 # +switch-master the_master 172.25.0.10 6379 172.25.0.12 6381 redis_sentinel_2 | 1:X 13 Oct 2022 10:14:35.055 * +slave slave 172.25.0.11:6380 172.25.0.11 6380 @ the_master 172.25.0.12 6381 redis_sentinel_2 | 1:X 13 Oct 2022 10:14:35.055 * +slave slave 172.25.0.10:6379 172.25.0.10 6379 @ the_master 172.25.0.12 6381 redis_sentinel_1 | 1:X 13 Oct 2022 10:15:04.122 # +sdown slave 172.25.0.10:6379 172.25.0.10 6379 @ the_master 172.25.0.12 6381 redis_sentinel_3 | 1:X 13 Oct 2022 10:15:04.122 # +sdown slave 172.25.0.10:6379 172.25.0.10 6379 @ the_master 172.25.0.12 6381 redis_sentinel_2 | 1:X 13 Oct 2022 10:15:05.079 # +sdown slave 172.25.0.10:6379 172.25.0.10 6379 @ the_master 172.25.0.12 6381
6. Cluster 集群
1) Cluster 配置文件
Redis Cluster 官方建议最少 6 个节点,准备如下 6 个节点。
(1) 创建 node_3 的 redis.conf 文件
在 /home/docker/redis_cluster/node_3/conf 目录下,创建 redis.conf 文件,内容如下:
bind 0.0.0.0 port 6379 protected-mode no slave-read-only no logfile /var/log/redis.log #dir /data cluster-enabled yes cluster-config-file node-3.conf masterauth pass123 requirepass pass123
(2) 创建 node_4 的 redis.conf 文件
在 /home/docker/redis_cluster/node_4/conf 目录下,创建 redis.conf 文件,内容如下:
bind 0.0.0.0 port 6379 protected-mode no slave-read-only no logfile /var/log/redis.log #dir /data cluster-enabled yes cluster-config-file node-4.conf masterauth pass123 requirepass pass123
(3) 创建 node_5 的 redis.conf 文件
在 /home/docker/redis_cluster/node_5/conf 目录下,创建 redis.conf 文件,内容如下:
bind 0.0.0.0 port 6379 protected-mode no slave-read-only no logfile /var/log/redis.log #dir /data cluster-enabled yes cluster-config-file node-5.conf masterauth pass123 requirepass pass123
(4) 创建 node_6 的 redis.conf 文件
在 /home/docker/redis_cluster/node_6/conf 目录下,创建 redis.conf 文件,内容如下:
bind 0.0.0.0 port 6379 protected-mode no slave-read-only no logfile /var/log/redis.log #dir /data cluster-enabled yes cluster-config-file node-6.conf masterauth pass123 requirepass pass123
(5) 创建 node_7 的 redis.conf 文件
在 /home/docker/redis_cluster/node_7/conf 目录下,创建 redis.conf 文件,内容如下:
bind 0.0.0.0 port 6379 protected-mode no slave-read-only no logfile /var/log/redis.log #dir /data cluster-enabled yes cluster-config-file node-7.conf masterauth pass123 requirepass pass123
(6) 创建 node_8 的 redis.conf 文件
在 /home/docker/redis_cluster/node_8/conf 目录下,创建 redis.conf 文件,内容如下:
bind 0.0.0.0 port 6379 protected-mode no slave-read-only no logfile /var/log/redis.log #dir /data cluster-enabled yes cluster-config-file node-8.conf masterauth pass123 # 主从认证密码 requirepass pass123 # 本地认证密码
2) 修改 common.env 文件
在 /home/docker/redis_cluster 目录下,修改 common.env 文件,内容如下:
REQUIRE_PASS=123456 MASTER_AUTH=123456 MASTER_HOST=redis_master MASTER_PORT=6379 CLUSTER_HOSTS=172.25.0.13:6379 172.25.0.14:6379 172.25.0.15:6379 172.25.0.16:6379 172.25.0.17:6379 172.25.0.18:6379 CLUSTER_PASS=pass123
3) 修改 run_redis_server.sh 文件
在 /home/docker/redis_cluster/scripts 目录下,修改 run_redis_server.sh 文件,内容如下:
#!/bin/bash if [[ $1 = 'master' ]]; then redis-server /etc/redis/redis.conf --requirepass $REQUIRE_PASS --masterauth $MASTER_AUTH elif [[ $1 = 'slave' ]]; then redis-server /etc/redis/redis.conf --slaveof $MASTER_HOST $MASTER_PORT --requirepass $REQUIRE_PASS --masterauth $MASTER_AUTH elif [[ $1 = 'cluster_normal' ]]; then redis-server /etc/redis/redis.conf elif [[ $1 = 'cluster_special' ]]; then redis-server /etc/redis/redis.conf echo "yes" | redis-cli --cluster create $CLUSTER_HOSTS --cluster-replicas 1 -a $CLUSTER_PASS else echo "Usage: $0 [master|slave|cluster_normal|cluster_special]" echo " master - Redis master" echo " slave - Redis slave" echo " cluster_normal - Redis cluster normal node" echo " cluster_special - Redis cluster special node" echo "" fi
4) 创建 docker-compose.yml
在 /home/docker/redis_cluster/cluster 目录下,创建 docker-compose.yml 文件,内容如下:
version: "3" services: redis_node_3: image: redis:6 container_name: redis_node_3 volumes: - /home/docker/redis_cluster/node_3/data:/data - /home/docker/redis_cluster/node_3/conf:/etc/redis - /home/docker/redis_cluster/node_3/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.13 command: /bin/bash /root/redis_scripts/run_redis_server.sh cluster_normal env_file: - /home/docker/redis_cluster/common.env redis_node_4: image: redis:6 container_name: redis_node_4 volumes: - /home/docker/redis_cluster/node_4/data:/data - /home/docker/redis_cluster/node_4/conf:/etc/redis - /home/docker/redis_cluster/node_4/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.14 command: /bin/bash /root/redis_scripts/run_redis_server.sh cluster_normal env_file: - /home/docker/redis_cluster/common.env redis_node_5: image: redis:6 container_name: redis_node_5 volumes: - /home/docker/redis_cluster/node_5/data:/data - /home/docker/redis_cluster/node_5/conf:/etc/redis - /home/docker/redis_cluster/node_5/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.15 command: /bin/bash /root/redis_scripts/run_redis_server.sh cluster_normal env_file: - /home/docker/redis_cluster/common.env redis_node_6: image: redis:6 container_name: redis_node_6 volumes: - /home/docker/redis_cluster/node_6/data:/data - /home/docker/redis_cluster/node_6/conf:/etc/redis - /home/docker/redis_cluster/node_6/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.16 command: /bin/bash /root/redis_scripts/run_redis_server.sh cluster_normal env_file: - /home/docker/redis_cluster/common.env redis_node_7: image: redis:6 container_name: redis_node_7 volumes: - /home/docker/redis_cluster/node_7/data:/data - /home/docker/redis_cluster/node_7/conf:/etc/redis - /home/docker/redis_cluster/node_7/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.17 command: /bin/bash /root/redis_scripts/run_redis_server.sh cluster_normal env_file: - /home/docker/redis_cluster/common.env redis_node_8: image: redis:6 container_name: redis_node_8 depends_on: - redis_node_3 - redis_node_4 - redis_node_5 - redis_node_6 - redis_node_7 volumes: - /home/docker/redis_cluster/node_8/data:/data - /home/docker/redis_cluster/node_8/conf:/etc/redis - /home/docker/redis_cluster/node_8/log:/var/log - /home/docker/redis_cluster/scripts:/root/redis_scripts networks: my_net: ipv4_address: 172.25.0.18 command: /bin/bash /root/redis_scripts/run_redis_server.sh cluster_special env_file: - /home/docker/redis_cluster/common.env networks: my_net: driver: bridge ipam: config: - subnet: 172.25.0.0/16
5) 启动
$ cd /home/docker/redis_cluster/cluster
$ docker-compose up -d
[+] Running 7/7 ⠿ Network cluster_my_net Created 0.0s ⠿ Container redis_node_6 Started 0.8s ⠿ Container redis_node_7 Started 0.7s ⠿ Container redis_node_3 Started 0.8s ⠿ Container redis_node_4 Started 1.0s ⠿ Container redis_node_5 Started 1.0s ⠿ Container redis_node_8 Started 1.6s
$ docker exec -it redis_node_8 /bin/bash
root@754fb446b99f:/data# redis-cli -c 127.0.0.1:6379> auth pass123 OK 127.0.0.1:6379> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:2 cluster_stats_messages_ping_sent:37 cluster_stats_messages_pong_sent:38 cluster_stats_messages_sent:75 cluster_stats_messages_ping_received:38 cluster_stats_messages_pong_received:37 cluster_stats_messages_received:75 127.0.0.1:6379> cluster nodes 4a93001b49bb2138c0a2c7f67369e47f1762ae7d 172.25.0.18:6379@16379 myself,slave c1095cc3609d0043fb8f7db7d2e728f89c19c5ee 0 1665898497000 2 connected c1095cc3609d0043fb8f7db7d2e728f89c19c5ee 172.25.0.14:6379@16379 master - 0 1665898499256 2 connected 5461-10922 98c22d70fedf2332629df0e065d5fa5dfbaa9964 172.25.0.16:6379@16379 slave d1604ceeb5fa2474e779468bb6f4566c1adee365 0 1665898497000 3 connected d1604ceeb5fa2474e779468bb6f4566c1adee365 172.25.0.15:6379@16379 master - 0 1665898498228 3 connected 10923-16383 c2f940037de7ff3a0b05611a9b70f56f0afa7a09 172.25.0.13:6379@16379 master - 0 1665898496171 1 connected 0-5460 1c834e5fbe2f61029f55a53e6f517ec8dcf87833 172.25.0.17:6379@16379 slave c2f940037de7ff3a0b05611a9b70f56f0afa7a09 0 1665898497193 1 connected
可以看到 redis_node_3、redis_node_4、redis_node_5 是 master,redis_node_6、redis_node_7、redis_node_8 是 slave。进入任意从节点,执行 info replicaiton 来再次验证。
$ docker exec -it redis_node_6 /bin/bash
root@15ccf6f9c9b8:/data# redis-cli -c 127.0.0.1:6379> auth pass123 OK 127.0.0.1:6379> info replication # Replication role:slave master_host:172.25.0.15 master_port:6379 master_link_status:up master_last_io_seconds_ago:9 master_sync_in_progress:0 slave_read_repl_offset:924 slave_repl_offset:924 slave_priority:100 slave_read_only:0 replica_announced:1 connected_slaves:0 master_failover_state:no-failover master_replid:f64ceb5694da9afbd96ec4fe96eb07f17d2f7922 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:924 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:924