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节点都下线了

docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

 但实际redis-slave节点是在线的,表明是sentinel认为redis-slave下线 了。可能是之间网络不通的原因导致的。

此时,查找其他网页,发现可以看到sentinel的logs。

查看sentinel的日志:

docker logs redis-sentinel-1

有:

docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

看日志,确实在sentinel启动后,redis-slave是下线了。

尝试1:

最开始看到WARN的信息:Device or resource busy,以为是设备被占用(conf文件会被sentinel再写入),就往这个方向解决:

出现这个Warning,原因可能是:不能修改配置文件,容器中的配置文件是挂载到外部的。(一般修改文件都是新生成一个然后替换原来的),就会报Device or resource busy.----->不是主要原因(因为发现其他可以正常故障迁移的也会有这个warning信息)

尝试2:
万能的防火墙、端口原因

docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

 检查本地的防火墙,发现防火墙是关闭的,不是我这边下线的原因。

尝试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搭建redis集群和Sentinel,实现故障转移-LMLPHP

上面特别强调docker的1:1端口映射。但没有给出具体的解决方案。

继续找寻解决方法:

https://cloud.tencent.com/developer/article/1343834 

docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

https://www.cnblogs.com/JulianHuang/p/12650721.html

 这篇文章具有决定性帮助作用,首先他考虑到了docker环境下端口映射问题,其次他考虑到了网络问题。

按照这篇文章从新搭建下,发现最后还是出现了redis-slave在sentinel一启动就下线的问题。

看评论,应该是配置文件中sentinel端口都一样,实际应该每个配置文件都不同的。按照这种方法进行修改,不幸的是,还是失败。

继续再这篇博客的思路上思考,里面提出了network和redis_defalut的网络配置,将重心放到解决这个上面。

最开始在配置文件中配置这个,启动redis-sentinel集群会报错:

docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

 按照上面的提示,进行docker network create redis_default操作,应该是创建这个网络,就可以成功启动sentinel集群。

按照道理说,redis-master中应该有自己的network信息的,可能是这篇博主的network信息是redis_default和我机器上的不同,不然怎么会又要创建一个。按照这个思路,进入到redis-master容器中,查看信息。

docker inspect redis-master

发现:

docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

 确实,我的机器上加redisconf_default

到这算是有个突破口了。

根据这几轮的探索,主要针对最后一篇博客做了如下几个点的修改:
1)redis集群的端口对应是:

63796379
63806379
63816379

这样在commondmaster的端口才是6379,sentinel.conf中的端口也是6379。

2)sentinel文件夹的docker-compose.yml

networks:
  default:
    external:
      name: redisconf_default

3)sentinel.conf

sentinel1.confsentinel2.confsentinel3.confport都不相同,分别是263792638026381 。

sentinel monitorip地址是master节点的dockerip地址,port就是masterport

经过上面的修改,发现故障迁移是成功的。

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

docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

 关键的是上面的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看日志:

docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

之前mymaster的192.168网段(错误的配置下)变成和现在slave的同网段了,就可以ping通了,后面没有+sdown slave的信息。就会一直阻塞在这,等待新的操作记录日志。

此时在另一个窗口关闭master节点:docker stop redis-master

日志为:

docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

进入到sentinel的redis-cli中,sentinel slaves mymaster查看,slave都启动的

 docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

 docker搭建redis集群和Sentinel,实现故障转移-LMLPHP

至此,搭建集群应该成功,有问题再记录解决。

03-07 22:48