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都启动的


至此,搭建集群应该成功,有问题再记录解决。
docker搭建redis集群和Sentinel,实现故障转移的更多相关文章
- docker搭建redis集群
一.简介 docker作为一个容器技术,在搭建资源隔离性服务上具有很大的优势,在一台服务器上可以启动多个docker容器,感觉每个在容器里面部署的服务就像是部署在不同的服务器上.此次基于docker以 ...
- 利用Docker搭建Redis集群
Redis集群搭建 运行Redis镜像 分别使用以下命令启动3个Redis docker run --name redis-6379 -p 6379:6379 -d hub.c.163.com/lib ...
- Docker:Docker搭建Redis集群(6)
国外的公有云实在是太慢了,经常time out 这里搜集几个国内出名的: hub.c.163.com (网易:https://c.163.com/hub#/m/home/) dev.aliyun.co ...
- 5分钟实现用docker搭建Redis集群模式和哨兵模式
如果让你为开发.测试环境分别搭一套哨兵和集群模式的redis,你最快需要多久,或许你需要一天?2小时?事实是可以更短. 是的,你已经猜到了,用docker部署,真的只需要十几分钟. 一.准备工作 拉取 ...
- 使用docker搭建redis集群
创建网卡 docker network create redis --subnet 172.20.0.0/ --gateway 172.20.0.1 通过脚本创建6个redis配置 for i in ...
- docker 搭建 redis 集群(哨兵模式)
文件结构 1. redis-sentinel 1-1. docker-compose.yml 1-2. sentinel 1-2-1 docker-compose.yml 1-2-2 sentinel ...
- 基于Docker的redis集群搭建
Redis集群官方介绍:http://www.redis.cn/topics/cluster-tutorial.html 基于Docker搭建Redis集群 环境:6个节点,三主三从 制作Redis镜 ...
- docker 实现redis集群搭建
摘要:接触docker以来,似乎养成了一种习惯,安装什么应用软件都想往docker方向做,今天就想来尝试下使用docker搭建redis集群. 首先,我们需要理论知识:Redis Cluster是Re ...
- 从零开始学习docker之在docker中搭建redis(集群)
docker搭建redis集群 docker-compose是以多容器的方式启动,非常适合用来启动集群 一.环境准备 云环境:CentOS 7.6 64位 二.安装docker-compose #需要 ...
随机推荐
- Network UVA - 315 无向图找割点
题意: 给你一个无向图,你需要找出来其中有几个割点 割点/割项: 1.u不为搜索起点,low[v]>=dfn[u] 2.u为搜索起点,size[ch]>=2 3.一般情况下,不建议在tar ...
- Entity Framework中Remove、Modified实体时,在修改或删除时引发主键冲突的问题
问题: try { string fileId = context.NewsT.Where(t => t.Id == Model.Id).FirstOrDefault().FileId; str ...
- [Golang]-2 Map关联数组与下划线(_)的意义
目录 map 下划线(underscore) 用在import 用在返回值 用在变量 map map 是 Go 内置关联数据类型(在一些其他的语言中称为哈希 或者字典 ). func main() { ...
- 【原创】k8s之job和Cronjob
1.失败任务 apiVersion: batch/v1 kind: Job metadata: name: bad spec: template: metadata: name: bad spec: ...
- Cobbler服务部署
1.安装epel源 yum -y install epel-release 2.安装cobbler环境所需的包 yum install -y httpd dhcp xinetd tftp cobble ...
- servlet相关知识点
一.servlet的生命周期 Servlet(Sever Applet),全称是Java Servlet,是用java编写的服务器程序.Servlet是指任何实现了这个Servlet接口的类. ser ...
- codeforces 1042D - Petya and Array【树状数组+离散化】
题目:戳这里 题意:有n个数,问有多少个区间满足[L,R]内的和小于t. 解题思路: [L,R]内的和小于t等价于sum[R]-sum[L-1]<t,将sum[L-1]左移,可以看出R与L的关系 ...
- C++ 结构体 segment fault
形如 struct node { int key; int height; int size; //tree node 个数 node *left, *right; node(int x) : key ...
- hautoj 1268 小天使改名
1268: 小天使改名 时间限制: 2 秒 内存限制: 128 MB提交: 437 解决: 123提交 状态 题目描述 小天使的b站帐号被大家发现啦.于是小天使决定改名,将他原有ID中的两个不同位 ...
- Leetcode(870)-优势洗牌
给定两个大小相等的数组 A 和 B,A 相对于 B 的优势可以用满足 A[i] > B[i] 的索引 i 的数目来描述. 返回 A 的任意排列,使其相对于 B 的优势最大化. 示例 1: 输入: ...