怎么用docker搭建redis主从哨兵模式,并整合进springboot项目
这篇文章主要介绍"怎么用docker搭建redis主从哨兵模式,并整合进springboot项目",在日常操作中,相信很多人在怎么用docker搭建redis主从哨兵模式,并整合进springboot项目问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"怎么用docker搭建redis主从哨兵模式,并整合进springboot项目"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
一,在主机上搭建redis
整体redis和哨兵架构均为3节点(1主2从)
默认容器启动为bridge模式,这样哨兵取到的主节点ip为容器内网ip,客户端无法访问容器内网,故需要使用宿主机网络模式编排(network_mode:"host")
宿主机外网IP,192.168.1.254
1,(redis编排文件)master-slave/docker-compose.yml
version: "3"services: master: image: redis:latest container_name: redis-master command: redis-server --requirepass 123456 --port 6379 ports: - "6379" network_mode: "host" slave1: image: redis:latest container_name: redis-slave-1 command: redis-server --port 6380 --slaveof 192.168.1.254 6379 --requirepass 123456 --masterauth 123456 depends_on: - master ports: - "6380" network_mode: "host" slave2: image: redis:latest container_name: redis-slave-2 command: redis-server --port 6381 --slaveof 192.168.1.254 6379 --requirepass 123456 --masterauth 123456 depends_on: - master ports: - "6381" network_mode: "host"
在当前目录下使用命令启动:docker-compose up -d
共三台redis,其中master(6379),slave(6380,6381)
2,(哨兵编排文件)sentinel/docker-compose.yml
# Example sentinel.conf can be downloaded from http://download.redis.io/redis-stable/sentinel.confversion: "3"services: sentinel1: image: redis:latest container_name: redis-sentinel-1 command: redis-sentinel /usr/local/etc/redis/sentinel.conf ports: - "26379" volumes: - "/root/redis/sentinel1.conf:/usr/local/etc/redis/sentinel.conf" network_mode: "host" sentinel2: image: redis:latest container_name: redis-sentinel-2 command: redis-sentinel /usr/local/etc/redis/sentinel.conf ports: - "26380" volumes: - "/root/redis/sentinel2.conf:/usr/local/etc/redis/sentinel.conf" network_mode: "host" sentinel3: image: redis:latest container_name: redis-sentinel-3 command: redis-sentinel /usr/local/etc/redis/sentinel.conf ports: - "26381" volumes: - "/root/redis/sentinel3.conf:/usr/local/etc/redis/sentinel.conf" network_mode: "host"
在当前目录下使用命令启动:docker-compose up -d
共三台哨兵,端口分别为26379, 26380, 26381
其中三个哨兵配置文件内容除了端口不同,其他内容均相同
/root/redis/sentinel1.conf
port 26379 # 其他两节点分别为26380, 26381dir /tmpsentinel monitor mymaster 192.168.1.254 6379 2sentinel auth-pass mymaster 123456sentinel down-after-milliseconds mymaster 30000sentinel parallel-syncs mymaster 1sentinel failover-timeout mymaster 10000sentinel deny-scripts-reconfig yes
#第三行表示Redis监控一个叫做mymaster的运行在192.168.1.254:6379的master,投票达到2则表示master以及挂掉了。
#第四行设置主节点的认证密码
#第五行表示在一段时间范围内sentinel向master发送的心跳PING没有回复则认为master不可用了。
#第六行的parallel-syncs表示设置在故障转移之后,同时可以重新配置使用新master的slave的数量。数字越低,更多的时间将会用故障转移完成,但是如果slaves配置为服务旧数据,你可能不希望所有的slave同时重新同步master。因为主从复制对于slave是非阻塞的,当停止从master加载批量数据时有一个片刻延迟。通过设置选项为1,确信每次只有一个slave是不可到达的。
#第七行表示10秒内mymaster还没活过来,则认为master宕机了。
这是启动后的容器列表:
二,整合springboot项目
1,引入依赖
org.springframework.boot spring-boot-starter-data-redis
2,配置application.yml
spring: redis: sentinel: master: mymaster nodes: - "192.168.1.254:26379" - "192.168.1.254:26380" - "192.168.1.254:26381" host: 192.168.1.254 password: 123456 jedis: pool: min-idle: 8 max-active: 100 max-wait: 3000 max-idle: 100
3,使用RedisTemplate操作redis
@Autowired RedisTemplateredisTemplate; @Test public void testRedisMasterSlave() throws Exception { ValueOperations valueOperations = redisTemplate.opsForValue(); ExecutorService es = Executors.newFixedThreadPool(3); for (int j = 0; j < 3; j++) { es.submit(() -> { for (int i = 0; i < 1000; i++) { try { String threadName = Thread.currentThread().getName(); valueOperations.set(threadName+i, i+"", 30L, TimeUnit.MINUTES); TimeUnit.MILLISECONDS.sleep(200L); } catch (InterruptedException e) { System.out.println("error: " + e.getMessage()); } } }); } es.shutdown(); es.awaitTermination(30L, TimeUnit.MINUTES); }
这里使用3个线程模拟并发写入redis,在写的过程中,停掉master,查看控制台输出日志
2019-10-06 18:52:51.949 INFO 128972 --- [pool-1-thread-1] io.lettuce.core.EpollProvider : Starting without optional epoll library2019-10-06 18:52:51.951 INFO 128972 --- [pool-1-thread-1] io.lettuce.core.KqueueProvider : Starting without optional kqueue library2019-10-06 18:53:55.979 INFO 128972 --- [xecutorLoop-1-8] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was /192.168.1.254:63792019-10-06 18:53:57.992 WARN 128972 --- [ioEventLoop-4-4] i.l.core.protocol.ConnectionWatchdog : Cannot reconnect: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /192.168.1.254:63792019-10-06 18:54:02.277 INFO 128972 --- [xecutorLoop-1-7] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was 192.168.1.254:63792019-10-06 18:54:04.286 WARN 128972 --- [ioEventLoop-4-2] i.l.core.protocol.ConnectionWatchdog : Cannot reconnect: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /192.168.1.254:63792019-10-06 18:54:08.577 INFO 128972 --- [xecutorLoop-1-4] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was 192.168.1.254:63792019-10-06 18:54:10.587 WARN 128972 --- [ioEventLoop-4-8] i.l.core.protocol.ConnectionWatchdog : Cannot reconnect: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /192.168.1.254:63792019-10-06 18:54:15.678 INFO 128972 --- [xecutorLoop-1-3] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was 192.168.1.254:63792019-10-06 18:54:17.687 WARN 128972 --- [ioEventLoop-4-6] i.l.core.protocol.ConnectionWatchdog : Cannot reconnect: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /192.168.1.254:63792019-10-06 18:54:22.877 INFO 128972 --- [xecutorLoop-1-7] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was 192.168.1.254:63792019-10-06 18:54:24.885 WARN 128972 --- [ioEventLoop-4-2] i.l.core.protocol.ConnectionWatchdog : Cannot reconnect: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: /192.168.1.254:63792019-10-06 18:54:29.078 INFO 128972 --- [xecutorLoop-1-1] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was 192.168.1.254:63792019-10-06 18:54:29.085 INFO 128972 --- [ioEventLoop-4-4] i.l.core.protocol.ReconnectionHandler : Reconnected to 192.168.1.254:6380
可以看到在18:53:55.979,已经连不上主节点了(6379),之后一直在重连,直到18:54:29.085才连上,但是这时候的节点已经变了(6380),证明哨兵已经可以自动切换主节点了。
再看redis中的数据,一共3000条数据,一条没丢,证明即使在切换主备的过程中,数据也不会丢
接着启动刚停掉的redis-master节点,发现已经启动不了了,报错
2019-10-05T16:00:57.899358510Z 1:S 05 Oct 2019 16:00:57.897 * Connecting to MASTER 192.168.1.254:63802019-10-05T16:00:57.899381586Z 1:S 05 Oct 2019 16:00:57.897 * MASTER <-> REPLICA sync started2019-10-05T16:00:57.899385377Z 1:S 05 Oct 2019 16:00:57.897 * Non blocking connect for SYNC fired the event.2019-10-05T16:00:57.899388194Z 1:S 05 Oct 2019 16:00:57.898 * Master replied to PING, replication can continue...2019-10-05T16:00:57.899391119Z 1:S 05 Oct 2019 16:00:57.898 * (Non critical) Master does not understand REPLCONF listening-port: -NOAUTH Authentication required.2019-10-05T16:00:57.899401303Z 1:S 05 Oct 2019 16:00:57.898 * (Non critical) Master does not understand REPLCONF capa: -NOAUTH Authentication required.2019-10-05T16:00:57.899404228Z 1:S 05 Oct 2019 16:00:57.898 * Partial resynchronization not possible (no cached master)2019-10-05T16:00:57.899406828Z 1:S 05 Oct 2019 16:00:57.898 # Unexpected reply to PSYNC from master: -NOAUTH Authentication required.2019-10-05T16:00:57.899409536Z 1:S 05 Oct 2019 16:00:57.898 * Retrying with SYNC...2019-10-05T16:00:57.899412136Z 1:S 05 Oct 2019 16:00:57.899 # MASTER aborted replication with an error: NOAUTH Authentication required.
这时候已经作为从节点连接新主节点了,但是授权认证失败,因为之前主节点根本就没有配置slaveof,这里我以为哨兵会自动加上slaveof配置,但是没有,难道是没有使用配置文件的缘故?
已经找到原因,并且在这篇中完全实现了
到此,关于"怎么用docker搭建redis主从哨兵模式,并整合进springboot项目"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!