docker搭建redis集群和Sentinel,实现故障转移
0.引言
公司开发需要用到redis,虽然有运维自动搭建,还是记录下如何搭建redis集群和Sentinel。
采用的是vagrant虚拟机+docker的方式进行搭建。
搭建思路:
首先是借鉴下其他博客的docker搭建步骤,直接搭建。主要是:
https://blog.csdn.net/qq_40369435/article/details/91357479
然后就是记录搭建过程中遇到的问题,以及如何一步步解决的。
最后测试。
搭建的集群是:
redis集群:1主2从
sentinel集群:3台
1.基础安装
注:基础安装是根据已有博客搭建的,有很多问题,不是最终步骤。最终步骤在第三部分总结给出,当然也可能有问题,毕竟各个环境可能不同。
(1)在虚拟机中安装docker-compose
默认已经安装过了docker。
1)拉取安装包
curl -L "https://get.daocloud.io/docker/compose/releases/download/1.27.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
2)给docker-compose增加执行权限
chmod +x /usr/local/bin/docker-compose
注:最开始安装docker-compose是先安装python的pip,再通过pip安装docker-compose,但升级pip时问题太多,干脆直接找个拉取源代码的直接下载。惭愧之前搞了那么久的python。
(2)搭建redis集群
1)新建docker-compose.yml文件
version: '2.0' services: master: image: redis container_name: redis-master ports: - 6379:6379 slave1: image: redis container_name: redis-slave-1 ports: - 6380:6379 command: redis-server --slaveof redis-master 6379 slave2: image: redis container_name: redis-slave-2 ports: - 6381:6379 command: redis-server --slaveof redis-master 6379
2)启动redis集群
docker-compose up -d
启动后,
docker ps; # 查看容器启动情况
如果容器启动不成功,docker ps不会列出正在运行的容器,需要查看已经启动过的容器
docker ps -a; #查看启动过的容器
这个时候,如果启动失败,通过docker ps -a知道启动失败的容器id,再通过查看日志的方式找出错误:
docker logs 容器id(一部分即可); # 查看容器的日志
docker logs -f 容器id(一部分即可); # 动态查看容器的日志
(3)搭建sentinel集群
1)sentinel配置文件
一共三台sentinel,准备三份配置文件,分别是sentinel1.conf、sentinel2.conf和sentinel3.conf,将这三份配置文件放在
/usr/local/etc/redis/sentinel.conf目录下。
port 26379 dir "/tmp" # 自定义集群名,其中 127.0.0.1 为 redis-master 的 ip,6379 为 redis-master 的端口,2 为最小投票数(因为有 3 台 Sentinel 所以可以设置成 2) sentinel deny-scripts-reconfig yes #自己的虚拟机ip地址 sentinel monitor mymaster 192.168.165.10 6379 2 sentinel config-epoch mymaster 0 sentinel leader-epoch mymaster 0 # Generated by CONFIG REWRITE(后面这3个注释掉了) # sentinel known-replica mymaster 172.26.0.2 6379 # sentinel known-replica mymaster 172.26.0.3 6379 # sentinel current-epoch 0
同样的内容,复制到sentinel2.conf和sentinel3.conf'
2)docker-compose.yml
version: '2.0' services: sentinel1: image: redis container_name: redis-sentinel-1 ports: - 26379:26379 command: redis-sentinel /usr/local/etc/redis/sentinel.conf volumes: - ./sentinel1.conf:/usr/local/etc/redis/sentinel.conf sentinel2: image: redis container_name: redis-sentinel-2 ports: - 26380:26379 command: redis-sentinel /usr/local/etc/redis/sentinel.conf volumes: - ./sentinel2.conf:/usr/local/etc/redis/sentinel.conf sentinel3: image: redis container_name: redis-sentinel-3 ports: - 26381:26379 command: redis-sentinel /usr/local/etc/redis/sentinel.conf volumes: - ./sentinel3.conf:/usr/local/etc/redis/sentinel.conf
docker-compose.yml文件也放在/usr/local/etc/redis/sentinel.conf目录下
3)启动sentinel集群
docker-compose up -d
redis集群和sentinel集群按照上面步骤,可以通过docker运行,以为已经搭建成功,也可以连接到redis集群中。测试在主库中写,两个从库中都可以读出来,从库也不可以写内容。但是测试主库下线时,此时2个从库并没有有一个切换到主库。开始进行找错。
2.找问题与解决
主要问题:
redis集群的主从是成功的,但故障迁移时是失败的。
先看看测试故障迁移的方法:
1)进入redis-master容器
docker exec -it redis-master /bin/bash
2)进入redis环境
redis-cli -p 6379
3)查看redis角色
info
查看,知道redis-master是master节点。同样步骤查看redis-slave-1和redis-slave-2,都是slave节点
4)停掉master节点
docker stop redis-master
再去查看redis-slave-1和redis-slave-2,发现这两个节点还是slave,并没有一个成为master,表示sentinel故障转移失败。
注:之前没有找到查看sentinel日志的方法(docker logs -f 容器id),在master节点下线时直接查看sentinel的日志可以直观看到redis的下线、选举和当选主节点的过程。
初步认为原因可能是sentinel监控节点失败的原因:
查看过程:
1)进入到redis-sentinel-1节点,查看节点信息
docker exec -it redis-sentinel-1/bin/bash redis-cli -p 26379 sentinel master mymaster sentinel slaves mymaster
2)发现redis-slave节点都下线了
但实际redis-slave节点是在线的,表明是sentinel认为redis-slave下线 了。可能是之间网络不通的原因导致的。
此时,查找其他网页,发现可以看到sentinel的logs。
查看sentinel的日志:
docker logs redis-sentinel-1
有:
看日志,确实在sentinel启动后,redis-slave是下线了。
尝试1:
最开始看到WARN的信息:Device or resource busy,以为是设备被占用(conf文件会被sentinel再写入),就往这个方向解决:
出现这个Warning,原因可能是:不能修改配置文件,容器中的配置文件是挂载到外部的。(一般修改文件都是新生成一个然后替换原来的),就会报Device or resource busy.----->不是主要原因(因为发现其他可以正常故障迁移的也会有这个warning信息)
尝试2:
万能的防火墙、端口原因
检查本地的防火墙,发现防火墙是关闭的,不是我这边下线的原因。
尝试3:
sentinel.conf配置文件问题,没有开启参数
https://blog.csdn.net/weixin_30649859/article/details/97698005
按照上面思路解决,仍然行不通
尝试4:
找到关键性原因:sentinel和slave不能通信,导致sentinel认为slave下线了---》主动下线
https://blog.csdn.net/woluoyifan/article/details/84252705
https://www.cnblogs.com/erbiao/archive/2018/06/08/9156215.html
上面特别强调docker的1:1端口映射。但没有给出具体的解决方案。
继续找寻解决方法:
https://cloud.tencent.com/developer/article/1343834
https://www.cnblogs.com/JulianHuang/p/12650721.html
这篇文章具有决定性帮助作用,首先他考虑到了docker环境下端口映射问题,其次他考虑到了网络问题。
按照这篇文章从新搭建下,发现最后还是出现了redis-slave在sentinel一启动就下线的问题。
看评论,应该是配置文件中sentinel端口都一样,实际应该每个配置文件都不同的。按照这种方法进行修改,不幸的是,还是失败。
继续再这篇博客的思路上思考,里面提出了network和redis_defalut的网络配置,将重心放到解决这个上面。
最开始在配置文件中配置这个,启动redis-sentinel集群会报错:
按照上面的提示,进行docker network create redis_default操作,应该是创建这个网络,就可以成功启动sentinel集群。
按照道理说,redis-master中应该有自己的network信息的,可能是这篇博主的network信息是redis_default和我机器上的不同,不然怎么会又要创建一个。按照这个思路,进入到redis-master容器中,查看信息。
docker inspect redis-master
发现:
确实,我的机器上加redisconf_default
到这算是有个突破口了。
根据这几轮的探索,主要针对最后一篇博客做了如下几个点的修改:
1)redis集群的端口对应是:
6379:6379 6380:6379 6381:6379
这样在commond中 master的端口才是6379,在sentinel.conf中的端口也是6379。
2)sentinel文件夹的docker-compose.yml
networks:
default:
external:
name: redisconf_default
3)sentinel.conf
sentinel1.conf、sentinel2.conf和sentinel3.conf的port都不相同,分别是26379、26380和26381 。
sentinel monitor的ip地址是master节点的dockerip地址,port就是master的port。
经过上面的修改,发现故障迁移是成功的。
3.最终安装步骤
下面是适合我的机器的最终安装步骤,经过测试可以行的通。但不能保证完全没有问题。有问题就解决呗。
(1)安装docker-compose
curl -L "https://get.daocloud.io/docker/compose/releases/download/1.27.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
(2)搭建redis集群
1)在/usr/local/etc/redis/redis.conf目录下,新建docker-compose.yml
version: '3' services: master: image: redis container_name: redis-master command: redis-server --requirepass redis_pwd --masterauth redis_pwd ports: - 6379:6379 slave1: image: redis container_name: redis-slave-1 ports: - 6380:6380 command: redis-server --slaveof redis-master 6379 --requirepass redis_pwd --masterauth redis_pwd slave2: image: redis container_name: redis-slave-2 ports: - 6381:6381 command: redis-server --slaveof redis-master 6379 --requirepass redis_pwd --masterauth redis_pwd
--requirepass:指定redis登陆的密码。redis集群指定了,sentinel也指定相同的,否则都不指定(没验证过)
2)docker-compose up -d启动redis集群
3)查看redis-master节点的docker-ip和network name
docker inspect redis-master
关键的是上面的redisconf_default和IPAddress
(2)搭建sentinel集群
1)在/usr/local/etc/redis/sentinel.conf目录下,新建docker-compose.yml
具体内容为:
version: '3' services: sentinel1: image: redis container_name: redis-sentinel-1 ports: - 26379:26379 command: redis-sentinel /usr/local/etc/redis/sentinel.conf volumes: - ./sentinel1.conf:/usr/local/etc/redis/sentinel.conf sentinel2: image: redis container_name: redis-sentinel-2 ports: - 26380:26380 command: redis-sentinel /usr/local/etc/redis/sentinel.conf volumes: - ./sentinel2.conf:/usr/local/etc/redis/sentinel.conf sentinel3: image: redis container_name: redis-sentinel-3 ports: - 26381:26381 command: redis-sentinel /usr/local/etc/redis/sentinel.conf volumes: - ./sentinel3.conf:/usr/local/etc/redis/sentinel.conf networks: default: external: name: redisconf_default
2)在/usr/local/etc/redis/sentinel.conf目录下,新建sentinel1.conf、sentinel2.conf和sentinel3.conf
sentinel1.conf
port 26379 dir /tmp sentinel monitor mymaster 172.20.0.3 6379 2 sentinel auth-pass mymaster redis_pwd sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes
sentinel2.conf的port为26380,sentinel3.conf的port为26381,其他都一样
3)docker-compose up -d启动sentinel集群
4.测试
sentinel启动之后,通过docker logs -f sentinel容器id看日志:
之前mymaster的192.168网段(错误的配置下)变成和现在slave的同网段了,就可以ping通了,后面没有+sdown slave的信息。就会一直阻塞在这,等待新的操作记录日志。
此时在另一个窗口关闭master节点:docker stop redis-master
日志为:
进入到sentinel的redis-cli中,sentinel slaves mymaster查看,slave都启动的
至此,搭建集群应该成功,有问题再记录解决。