Docker安装redis Sentinel(高可用)
redis介绍
redis集群有两种,一种是redis sentinel(哨兵),高可用集群,同时只有一个master,各实例数据保持一致;一种是redis cluster,分布式集群,同时有多个master,数据分片部署在各个master上。 哨兵模式简单说就是在后台有一个监控,监控当前的主机并巡逻主机下面的从机,如果某一时刻主机挂掉了,那么他会通过一种投票的机制从从机之中选举一台作为新的主机,并且其余的从机将会连接到这个新的主机上面,完成故障转移,主从模式就是一个中心化的结构,通过哨兵完成去中心化;本次要搭建的是redis sentinel。
Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:
- 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
- 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
- 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
目录结构
1 2 3 4 5 6 7 8 9
| redis |--master |--slave1 |--slave2 |--Dockerfile |--redis.conf |--docker-compose.yml |--sentinel.conf |--start.sh
|
制作镜像
整个集群可以分为一个master,N个slave,M个sentinel,本次以2个slave和3个sentinel为例
增加redis.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| # 使用守护进程模式 daemonize no # 非保护模式,可以外网访问 protected-mode no timeout 300 databases 16 rdbcompression yes # 学习开发,使用最大日志级别,能够看到最多的日志信息 loglevel debug port $redis_port ##授权密码,各个配置保持一致 ##暂且禁用指令重命名 ##rename-command ##开启AOF,禁用snapshot appendonly yes #slaveof redis-master $master_port slave-read-only yes maxclients 10000 maxmemory 1000mb
|
增加sentinel.conf
1 2 3 4 5 6
| port $sentinel_port dir "/tmp" sentinel monitor mymaster redis-master $master_port 2 sentinel down-after-milliseconds mymaster 60000 sentinel failover-timeout manager1 180000 sentinel parallel-syncs manager1 2
|
这四行配置为一组,因为我们只有一个 master 节点,所以只配置了一个 master,可以配置多个 master,不用配置 slave 的信息,因为 slave 能够被自动检测到(master 节点会有关于 slave 的消息)
其他选项的基本格式如下:
sentinel <选项的名字> <主服务器的名字> <选项的值>
auth-pass
:选项指定了 master 的连接密码。
down-after-milliseconds
:选项指定了 Sentinel 认为服务器已经断线所需的毫秒数。
failover-timeout
:如果在该时间(ms)内未能完成 failover 操作,则认为该 failover 失败。
parallel-syncs
:选项指定了在执行故障转移时,最多可以有多少个从服务器同时对新的主服务器进行同步,这个数字越小,完成故障转移所需的时间就越长。
添加start.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| cd /conf redis_role=$1 echo $redis_role if [ $redis_role = "master" ] ; then echo "master" sed -i "s/\$redis_port/$redis_port/g" redis.conf redis-server /conf/redis.conf elif [ $redis_role = "slave" ] ; then echo "slave" sed -i "s/\$redis_port/$redis_port/g" redis.conf sed -i "s/#slaveof/slaveof/g" redis.conf sed -i "s/\$master_port/$master_port/g" redis.conf redis-server /conf/redis.conf elif [ $redis_role = "sentinel" ] ; then echo "sentinel" sed -i "s/\$sentinel_port/$sentinel_port/g" sentinel.conf sed -i "s/\$master_port/$master_port/g" sentinel.conf redis-sentinel /conf/sentinel.conf else echo "unknow role!" fi #ifend
|
添加Dockerfile
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| FROM redis:4-alpine
RUN apk add --update tzdata ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
COPY redis.conf /conf/redis.conf COPY sentinel.conf /conf/sentinel.conf COPY start.sh /conf/start.sh RUN chmod +x /conf/start.sh && chown redis:redis /conf/* ENTRYPOINT ["sh","/conf/start.sh"] CMD ["master"]
|
build镜像
在当前目录执行以下命令,创建redis:v1镜像。
1
| docker build -t redis:v1 .
|
启动redis服务
在根目录创建master
,slave1
,slave2
目录。
创建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
| version: '3'
services: redis-master: container_name: redis-master build: context: ./master volumes: - /master/data:/data environment: redis_port: '16379' image: redis:v1 expose: - "16379" redis-slave1: container_name: redis-slave1 build: context:./slave1 volumes: - /slave1/data:/data environment: master_port: '16379' redis_port: '16380' expose: - "16380" command: - slave image: redis:v1 redis-slave2: container_name: redis-slave2 build: context:./slave2 volumes: - /slave2/data:/data environment: master_port: '16379' redis_port: '16380' expose: - "16380" command: - slave image: redis:v1 redis-sentinel-1: container_name: redis-sentinel-1 environment: master_port: '16379' sentinel_port: '16381' expose: - "16381" command: - sentinel depends_on: - "redis-master" - "redis-slave1" - "redis-slave2" image: redis:v1 redis-sentinel-2: container_name: redis-sentinel-2 environment: master_port: '16379' sentinel_port: '16381' expose: - "16381" command: - sentinel depends_on: - "redis-master" - "redis-slave1" - "redis-slave2" image: redis:v1 redis-sentinel-3: container_name: redis-sentinel-3 environment: master_port: '16379' sentinel_port: '16381' expose: - "16381" command: - sentinel depends_on: - "redis-master" - "redis-slave1" - "redis-slave2" image: redis:v1
|
运行以下命令以启动:
可以选择添加-d
参数以守护进程启动。
Redis Sentinel 故障转移测试
查看redis-master服务IP
1
| docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' redis-master
|
结果:
1 2
| [root@localhost redis] 172.18.0.2
|
查看mymaster节点IP
1
| docker exec redis-sentinel-1 redis-cli -p 16381 SENTINEL get-master-addr-by-name mymaster
|
结果:
1 2 3
| [root@localhost redis] 172.18.0.2 16379
|
连接client
1
| docker exec -it redis-master redis-cli -h 172.18.0.2 -p 16379
|
停止master节点
1
| docker pause redis-master
|
查询master主节点IP
注意:中间有时间间隔。
1
| docker exec redis-sentinel-1 redis-cli -p 16381 SENTINEL get-master-addr-by-name mymaster
|
结果:
1 2 3
| [root@localhost redis] 172.18.0.4 16380
|
恢复redis-master服务
1
| docker unpause redis-master
|
分别查看slave1,slave2服务IP
1 2 3 4
| [root@localhost redis] 172.18.0.4 [root@localhost redis] 172.18.0.3
|
停止主节点
1
| docker pause redis-slave1
|
查询主节点
1
| docker exec redis-sentinel-1 redis-cli -p 16381 SENTINEL get-master-addr-by-name mymaster
|
结果:
1 2 3
| localhost redis] 172.18.0.2 16379
|
至此,故障转移测试完成。
参考:
高可用Redis服务架构分析与搭建
Redis Sentinel 高可用服务架构搭建
Redis哨兵-实现Redis高可用
Redis Sentinel机制与用法(一)
Redis设置认证密码 Redis使用认证密码登录 在Redis集群中使用认证密码
Docker化高可用redis集群
Docker环境搭建redis集群(主从模式)
https://github.com/AliyunContainerService/redis-cluster/blob/master/test.sh
Redis 的 Sentinel 文档