docker容器中搭建Redis哨兵集群
下载Redis镜像
docker pull redis
创建Redis集群(一主两从)
创建主节点容器(redis-master)
[root@192 ~]# docker run -d -v --name redis-master \
> -p 16379:16379 -p 6379:6379
> -v /home/docker/redis/node-1/data:/data \
> -v /home/docker/redis/node-1/conf/redis.conf:/etc/local/redis/config/redis.conf \
> -v /home/docker/redis/node-1/sentinel/sentinel.conf:/etc/local/redis/sentinel.conf \
> redis /etc/local/redis/config/redis.conf
创建从节点容器1(redis-salver2)
[root@192 ~]# docker run -d -v --name redis-salver2 \
> -p 26379:26379 -p 6372:6372
> -v /home/docker/redis/node-2/data:/data \
> -v /home/docker/redis/node-2/conf/redis.conf:/etc/local/redis/config/redis.conf \
> -v /home/docker/redis/node-2/sentinel/sentinel.conf:/etc/local/redis/sentinel.conf \
> redis /etc/local/redis/config/redis.conf
创建从节点容器2(redis-salver3)
[root@192 ~]# docker run -d -v --name redis-salver3 \
> -p 26379:26379 -p 6373:6373
> -v /home/docker/redis/node-3/data:/data \
> -v /home/docker/redis/node-3/conf/redis.conf:/etc/local/redis/config/redis.conf \
> -v /home/docker/redis/node-3/sentinel/sentinel.conf:/etc/local/redis/sentinel.conf \
> redis /etc/local/redis/config/redis.conf
映射的问文件分别如下
- conf是redis的配置文件
- data存放备份的数据(rdb文件和aof文件)
- sentinel映射的是sentinel文件
redis.conf需要修改的配置
如需redis.conf整个内容可以查看另一篇文章:
在docker容器中搭建redis主从集群
master主节点的配置
protected-mode no # 关闭redis的保护模式
port 6379 #Redis节点的端口,用于单实例
replica-announce-ip 192.168.25.129 #节点IP
replica-announce-port 6379 #节点端口,用于集群
master从节点2的配置
protected-mode no # 关闭redis的保护模式
slaveof 192.168.25.129 6379 # 配置主节点地址
port 6372 #Redis节点的端口,用于单实例
replica-announce-ip 192.168.25.129 #节点IP
replica-announce-port 6372 #节点端口,用于集群
master从节点3的配置
protected-mode no # 关闭redis的保护模式
slaveof 192.168.25.129 6379 # 配置主节点地址
port 6373 #Redis节点的端口,用于单实例
replica-announce-ip 192.168.25.129 #节点IP
replica-announce-port 6373 #节点端口,用于集群
sentinel.cnf配置
# sentinel的端口,博主配置的三个sentinel集群端口分别是16379,26379,36379
port 16379
#守护进程模式
daemonize yes
# 192.168.25.129 6379:配置主节点的地址(sentinel会从主节点中获取从节点的信息);2表示超过2个sentinel节点认为主节点故障,就确定为主观下线,会对Redis的从节点进行选举,最终选出一个作为主节点。
sentinel monitor mymaster 192.168.25.129 6379 2
#表示超过5秒以后sentinel就认为该master节点不可用;默认是30s
sentinel down-after-milliseconds mymaster 5000
# 表示sentinel在完成Redis的主从切换的最长时间不超过60s
sentinel failover-timeout mymaster 60000
# sentinel的工作路径
dir "/data/sentinel"
# sentinel的日志文件
logfile "/data/sentinel/redis_16379.log"
查看启动是否成功
[root@192 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2418a425da04 redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:6373->6373/tcp, :::6373->6373/tcp, 0.0.0.0:36379->36379/tcp, :::36379->36379/tcp, 6379/tcp redis-salver3
b52a3da1b0e2 redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:6372->6372/tcp, :::6372->6372/tcp, 0.0.0.0:26379->26379/tcp, :::26379->26379/tcp, 6379/tcp redis-salver2
8a8550b51ed2 redis "docker-entrypoint.s…" 2 hours ago Up 2 hours 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp, 0.0.0.0:16379->16379/tcp, :::16379->16379/tcp redis-master
依次进入主节点和从节点启动sentinel哨兵
[root@192 ~]# docker exec -it redis-master /bin/bash
root@b52a3da1b0e2:/data# redis-sentinel /etc/local/redis/sentinel.conf
root@b52a3da1b0e2:/data# exit
exit
[root@192 ~]# docker exec -it redis-salver2 /bin/bash
root@2418a425da04:/data# redis-sentinel /etc/local/redis/sentinel.conf
root@b52a3da1b0e2:/data# exit
exit
[root@192 ~]# docker exec -it redis-salver3 /bin/bash
root@2418a425da04:/data# redis-sentinel /etc/local/redis/sentinel.conf
root@2418a425da04:/data# exit
exit
查看redis集群和sentinel状态
[root@192 ~]# docker exec -it redis-master /bin/bash
# 查询Redis集群的信息
root@8a8550b51ed2:/data# redis-cli -h 192.168.25.129 -p 6379 info Replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.25.129,port=6372,state=online,offset=1598878,lag=0
slave1:ip=192.168.25.129,port=6373,state=online,offset=1599017,lag=0
master_failover_state:no-failover
master_replid:b469875236492fa755c8d6b4b5775f59fb782612
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1599017
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:550442
repl_backlog_histlen:1048576
# 查詢sentinel集群信息
root@2418a425da04:/data# redis-cli -h 192.168.25.129 -p 16379 info Sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.25.129:6379,slaves=2,sentinels=3
到此,Redis的哨兵模式搭建完成!
RedisTemplate的哨兵模式
引入redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在application.yml配置文件中配置sentinel地址
spring:
redis:
sentinel:
master: mymaster #指定master名称
nodes: #指定sentinel集群信息
- 192.168.25.129:16379
- 192.168.25.129:26379
- 192.168.25.129:36379
设置Redis的读写分离(主节点进行写和修改的操作;从节点进行查询操作)
@Bean
public LettuceClientConfigurationBuilderCustomizer configurationBuilderCustomizer(){
return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
启动springboot测试
Decode SubscriptionCommand [type=SENTINEL, output=MapOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-14 11:57:58:160 DEBUG 19936 --- [ioEventLoop-4-1] i.l.core.protocol.RedisStateMachine : Decoded SubscriptionCommand [type=SENTINEL, output=MapOutput [output={name=mymaster, ip=192.168.25.129, port=6379, runid=665701ef648193a06fa31cb4a23491f05e7d2fca, flags=master, link-pending-commands=0, link-refcount=1, last-ping-sent=0, last-ok-ping-reply=701, last-ping-reply=701, down-after-milliseconds=5000, info-refresh=9381, role-reported=master, role-reported-time=350639, config-epoch=0, num-slaves=2, num-other-sentinels=2, quorum=2, failover-timeout=60000, parallel-syncs=1}, error='null'], commandType=io.lettuce.core.protocol.Command], empty stack: true
11-14 11:57:58:160 DEBUG 19936 --- [ioEventLoop-4-1] io.lettuce.core.protocol.CommandHandler : [channel=0x2da4d9cf, /192.168.25.1:63120 -> /192.168.25.129:16379, chid=0x1] Stack contains: 1 commands
11-14 11:57:58:161 DEBUG 19936 --- [ioEventLoop-4-1] i.l.core.protocol.RedisStateMachine : Decode SubscriptionCommand [type=SENTINEL, output=ListOfMapsOutput [output=[], error='null'], commandType=io.lettuce.core.protocol.Command]
11-14 11:57:58:163 DEBUG 19936 --- [ioEventLoop-4-1] i.l.core.protocol.RedisStateMachine : Decoded SubscriptionCommand [type=SENTINEL, output=ListOfMapsOutput [output=[{name=192.168.25.129:6372, ip=192.168.25.129, port=6372, runid=3df2c7a03aa66b12d7e32d931489ebb3fa7ee897, flags=slave, link-pending-commands=0, link-refcount=1, last-ping-sent=0, last-ok-ping-reply=705, last-ping-reply=705, down-after-milliseconds=5000, info-refresh=8728, role-reported=slave, role-reported-time=350625, master-link-down-time=0, master-link-status=ok, master-host=192.168.25.129, master-port=6379, slave-priority=100, slave-repl-offset=55965, replica-announced=1}, {name=192.168.25.129:6373, ip=192.168.25.129, port=6373, runid=c036b70d72d6223a99b6901858588e8473795713, flags=slave, link-pending-commands=0, link-refcount=1, last-ping-sent=0, last-ok-ping-reply=705, last-ping-reply=705, down-after-milliseconds=5000, info-refresh=8728, role-reported=slave, role-reported-time=350624, master-link-down-time=0, master-link-status=ok, master-host=192.168.25.129, master-port=6379, slave-priority=100, slave-repl-offset=55965, replica-announced=1}], error='null'], commandType=io.lettuce.core.protocol.Command], empty stack: true
// 写的部分日志
[channel=0xfbe4ad65, /192.168.25.1:63129 -> /192.168.25.129:6379, chid=0xa] Stack contains: 1 commands
11-14 11:58:31:232 DEBUG 19936 --- [ioEventLoop-4-2] i.l.core.protocol.RedisStateMachine : Decode AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-14 11:58:31:232 DEBUG 19936 --- [ioEventLoop-4-2] i.l.core.protocol.RedisStateMachine : Decoded AsyncCommand [type=SET, output=StatusOutput [output=OK, error='null'], commandType=io.lettuce.core.protocol.Command], empty stack: true
// 读的部分日志
dispatching command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]
11-14 11:58:42:156 DEBUG 19936 --- [nio-8080-exec-7] i.lettuce.core.protocol.DefaultEndpoint : [channel=0x9479635e, /192.168.25.1:63127 -> /192.168.25.129:6373, epid=0x8] write() writeAndFlush command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command]