Docker Compose——搭建Redis集群
Posted Starzkg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker Compose——搭建Redis集群相关的知识,希望对你有一定的参考价值。
环境配置
Docker 18.x
Docker-Compose 3.7
Redis 6.2.5
主从(Master-Slave)模式
主从复制模式中包含一个主数据库实例(master)与一个或多个从数据库实例(slave),如下图
客户端可对主数据库进行读写操作,对从数据库进行读操作,主数据库写入的数据会实时自动同步给从数据库。
主从模式的具体工作机制
- slave启动后,向master发送SYNC命令,master接收到SYNC命令后通过bgsave保存快照(即上文所介绍的RDB持久化),并使用缓冲区记录保存快照这段时间内执行的写命令
- master将保存的快照文件发送给slave,并继续记录执行的写命令
- slave接收到快照文件后,加载快照文件,载入数据
- master快照发送完后开始向slave发送缓冲区的写命令,slave接收命令并执行,完成复制初始化
- 此后master每次执行一个写命令都会同步发送给slave,保持master与slave之间数据的一致性
主从模式的特点
- 主服务器负责接收写请求
- 从服务器负责接收读请求
- 从服务器的数据由主服务器复制过去。主从服务器的数据是一致的
主从模式的优点
- 读写分离(主服务器负责写,从服务器负责读)
- 高可用(某一台从服务器挂了,其他从服务器还能继续接收请求,不影响服务)
- 处理更多的并发量(每台从服务器都可以接收读请求,读QPS就上去了)
主从模式的缺点
- 不具备自动容错与恢复功能,master或slave的宕机都可能导致客户端请求失败,需要等待机器重启或手动切换客户端IP才能恢复
- master宕机,如果宕机前数据没有同步完,则切换IP后会存在数据不一致的问题
- 难以支持在线扩容,Redis的容量受限于单机配置
主从同步
主从架构的特点之一:主服务器和从服务器的数据是一致的。
主从同步的2种情况
完整的同步
从服务器向主服务器发送PSYNC命令
收到PSYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件。并用一个缓冲区来记录从现在开始执行的所有写命令。
当主服务器的BGSAVE命令执行完后,将生成的RDB文件发送给从服务器,从服务器接收和载入RBD文件。将自己的数据库状态更新至与主服务器执行BGSAVE命令时的状态。
主服务器将所有缓冲区的写命令发送给从服务器,从服务器执行这些写命令,达到数据最终一致性。
部分重同步
主从服务器的复制偏移量 主服务器每次传播N个字节,就将自己的复制偏移量加上N
从服务器每次收到主服务器的N个字节,就将自己的复制偏移量加上N
通过对比主从复制的偏移量,就很容易知道主从服务器的数据是否处于一致性的状态!
Docker-Compose
https://gitee.com/shentuzhigang/mini-project/tree/master/docker-compose/redis-master-slave
version: "3.7"
services:
redis1:
image: redis:latest
container_name: redis1
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf"
environment:
REDIS_PASSWORD: 123456
ports:
- 6376:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.81
redis2:
image: redis:latest
container_name: redis2
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf --replicaof 192.168.88.81 6379"
depends_on:
- redis1
environment:
REDIS_PASSWORD: 123456
ports:
- 6377:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.82
redis3:
image: redis:latest
container_name: redis3
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf --replicaof 192.168.88.81 6379"
depends_on:
- redis1
environment:
REDIS_PASSWORD: 123456
ports:
- 6378:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.83
networks:
redis-cluster-net:
external: true
name: redis-cluster-net
哨兵 Sentinel 模式
Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
- 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
- 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
Redis Sentinel 是一个分布式系统, 你可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器。
哨兵模式基于主从复制模式,只是引入了哨兵来监控与自动处理故障。如图
Docker-Compose
哨兵容器应该等待redis容器先启动,使用depends_on控制
version: "3.7"
services:
redis1:
image: redis:latest
container_name: redis1
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf"
environment:
REDIS_PASSWORD: 123456
ports:
- 6376:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.81
redis2:
image: redis:latest
container_name: redis2
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf --replicaof 192.168.88.81 6379"
depends_on:
- redis1
environment:
REDIS_PASSWORD: 123456
ports:
- 6377:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.82
redis3:
image: redis:latest
container_name: redis3
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf --replicaof 192.168.88.81 6379"
depends_on:
- redis1
environment:
REDIS_PASSWORD: 123456
ports:
- 6378:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.83
redis-sentinel1:
image: redis:latest
container_name: redis-sentinel1
command: /bin/bash -c "redis-sentinel /usr/local/etc/redis/redis-sentinel.conf"
depends_on:
- redis1
- redis2
- redis3
environment:
REDIS_PASSWORD: 123456
ports:
- 6373:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.84
redis-sentinel2:
image: redis:latest
container_name: redis-sentinel2
command: /bin/bash -c "redis-sentinel /usr/local/etc/redis/redis-sentinel.conf"
depends_on:
- redis1
- redis2
- redis3
environment:
REDIS_PASSWORD: 123456
ports:
- 6374:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.85
redis-sentinel3:
image: redis:latest
container_name: redis-sentinel3
command: /bin/bash -c "redis-sentinel /usr/local/etc/redis/redis-sentinel.conf"
depends_on:
- redis1
- redis2
- redis3
environment:
REDIS_PASSWORD: 123456
ports:
- 6375:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.86
networks:
redis-cluster-net:
external: true
name: redis-cluster-net
redis-sentinel.conf
sentinel monitor mymaster 192.168.88.81 6379 2
设置哨兵监控的主服务器和odown数(sdown数累计达到odown即开启故障转移主从切换) sentinel monitor
mymaster 192.168.11.128 6379 2
x秒不回应即单sentinel判定为sdown sentinel down-after-milliseconds
单次故障转移最长时间,超过则认定为故障转移失败 sentinel failover-timeout mymaster 10000
当发生failover主备切换时最多可以有多少个slave同时对新的master同步,数字越小favilover越快.通常设为1
sentinel parallel-syncs <master-name> <numslaves>
哨兵启动后自动写入的唯一id,每个sentinel不一样,故不能用同一份配置文件 sentinel myid
Redis Cluster 集群模式
Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation)。
Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令需要在多个 Redis 节点之间移动数据, 并且在高负载的情况下, 这些命令将降低 Redis 集群的性能, 并导致不可预测的行为。
Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
Redis 集群提供了以下两个好处:
- 将数据自动切分(split)到多个节点的能力。
- 当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。
Docker-Compose
version: "3.7"
services:
redis1:
image: redis:latest
container_name: redis1
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf"
environment:
REDIS_PASSWORD: 123456
ports:
- 6376:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.81
redis2:
image: redis:latest
container_name: redis2
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf"
environment:
REDIS_PASSWORD: 123456
ports:
- 6377:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.82
redis3:
image: redis:latest
container_name: redis3
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf"
environment:
REDIS_PASSWORD: 123456
ports:
- 6378:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.83
redis4:
image: redis:latest
container_name: redis4
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf"
environment:
REDIS_PASSWORD: 123456
ports:
- 6373:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.84
redis5:
image: redis:latest
container_name: redis5
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf"
environment:
REDIS_PASSWORD: 123456
ports:
- 6374:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.85
redis6:
image: redis:latest
container_name: redis6
command: /bin/bash -c "redis-server /usr/local/etc/redis/redis.conf"
environment:
REDIS_PASSWORD: 123456
ports:
- 6375:6379
volumes:
- type: bind
source: /root/redis-cluster/redis
target: /usr/local/etc/redis
networks:
redis-cluster-net:
ipv4_address: 192.168.88.86
networks:
redis-cluster-net:
external: true
name: redis-cluster-net
启动后执行命令
docker exec -it redis1 \\
redis-cli --cluster create \\
192.168.88.81:6379 \\
192.168.88.82:6379 \\
192.168.88.83:6379 \\
192.168.88.84:6379 \\
192.168.88.85:6379 \\
192.168.88.86:6379 \\
--cluster-replicas 1
Keepalived监控
通过 keepalived 的虚拟 IP,提供主从的统一访问,在主出现问题时, 通过 keepalived 运行脚本将从提升为主,待主恢复后先同步后自动变为主,该方案的好处是主从切换后,应用程序不需要知道(因为访问的虚拟 IP 不变),坏处是引入 keepalived 增加部署复杂性,在有些情况下会导致数据丢失。
Zookeeper监控
通过 zookeeper 来监控主从实例, 维护最新有效的 IP, 应用通过 zookeeper 取得 IP,对 Redis 进行访问,该方案需要编写大量的监控代码
常见问题
- [ERR] Node 192.168.162.132:7001 is not configured as a cluster node.
- Docker can’t connect to redis from another service
- Could not connect to Redis at 127.0.0.1:6379: Connection refused with homebrew
参考文章
以上是关于Docker Compose——搭建Redis集群的主要内容,如果未能解决你的问题,请参考以下文章
docker-compose搭建redis集群一主两从三哨兵