基于Docker搭建Redis一主二从三哨兵集群实战

前言

毕设中使用了 Redis 作为缓存,自己以往的项目中使用的都是单机的 Redis,这次要将单机的 Redis 实例改为 Redis 集群。

更新:这种方式部署有坑,外网环境下无法访问该集群,解决办法已更新在《Docker网络模型踩坑》。

搭建步骤

系统环境:Centos7.4 & Docker 18.09.2

首先拉取Redis镜像。

1
$ docker pull redis

搭建一主二从集群,yourpassword 为自定义密码,注意主从密码需要一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# master
$ docker run -it --name redis-master -d -p 6379:6379 redis redis-server --requirepass yourpassword --port 6379
$ docker exec -it redis-master bash
$ redis-cli -a yourpassword -p 6379
$ config set masterauth yourpassword

# slave1
$ docker run -it --name redis-slave1 -d -p 6380:6380 redis redis-server --requirepass yourpassword --port 6380
$ docker exec -it redis-slave1 bash
$ redis-cli -a yourpassword -p 6380
$ config set masterauth yourpassword

# slave2
$ docker run -it --name redis-slave2 -d -p 6381:6381 redis redis-server --requirepass yourpassword --port 6381
$ docker exec -it redis-slave2 bash
$ redis-cli -a yourpassword -p 6381
$ config set masterauth yourpassword

下载 Redis 官方的哨兵配置 sentinel.conf。

1
$ wget http://download.redis.io/redis-stable/sentinel.conf

查看 master 的 IP 地址。

1
$ docker inspect redis-master

即下面的”IPAddress”字段。

1
2
3
4
5
6
7
8
9
[
{
"Name": "/redis-master",
"NetworkSettings": {
"Gateway": "X.X.X.X",
"IPAddress": "X.X.X.X",
}
}
]

在 sentinel.conf 中配置以下字段。

1
2
3
4
5
port 26379
sentinel monitor mymaster X.X.X.X 6379 2
sentinel auth-pass mymaster yourpassword
daemonize yes
requirepass <sentinelpassword>

其中第三个参数为哨兵判断客观下线的法定人数,由于有 3 个哨兵,这里设为 2,不同哨兵的该值可以不同,即不同哨兵判断客观下线的条件可能不同。

复制多两份配置。

1
2
$ cp  sentinel.conf sentinel2.conf
$ cp sentinel.conf sentinel3.conf

再将 sentinel2.conf 和 sentinel3.conf 中的 port 分别改为 26380 与 26381。

启动三个哨兵。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# sentinel1
$ docker run -it --name redis-sentinel1 -d -p 26379:26379 -v /root/download/sentinel.conf:/usr/local/etc/redis/sentinel.conf -d redis /bin/bash
$ docker exec -it redis-sentinel1 bash
$ redis-sentinel /usr/local/etc/redis/sentinel.conf

# sentinel2
$ docker run -it --name redis-sentinel2 -d -p 26380:26380 -v /root/download/sentinel2.conf:/usr/local/etc/redis/sentinel.conf -d redis /bin/bash
$ docker exec -it redis-sentinel2 bash
$ redis-sentinel /usr/local/etc/redis/sentinel.conf

# sentinel3
$ docker run -it --name redis-sentinel3 -d -p 26381:26381 -v /root/download/sentinel3.conf:/usr/local/etc/redis/sentinel.conf -d redis /bin/bash
$ docker exec -it redis-sentinel3 bash
$ redis-sentinel /usr/local/etc/redis/sentinel.conf

检查哨兵启动是否成功。

1
2
3
$ docker exec -it redis-sentinel bash
$ redis-cli -p 26379
-> info

显示以下信息说明集群已启动成功。

1
2
3
4
5
6
7
# 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=X.X.X.X:6379,slaves=2,sentinels=3

下线 master,检测主从切换是否成功。

1
$ docker stop redis-master

等待一段时间,进入任意 sentinel 内部。

1
2
3
$ docker exec -it redis-sentinel bash
$ redis-cli -p 26379
-> info

可以看到主库已经成功切换。

1
2
3
4
5
6
7
# 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=X.X.X.X:6380,slaves=2,sentinels=3

或者输入 sentinel master mymaster,同样可以看到主库切换后的结果。

1
2
3
4
5
6
1) "name"
2) "mymaster"
3) "ip"
4) "X.X.X.X"
5) "port"
6) "6380"

注:即使重新启动原来的 redis-master 节点,集群也不会自动切换回该节点,需手动切换。

题外话:

1
2
3
4
# Sentinel
sentinel_masters:1
···
master0:name=mymaster,status=ok,address=X.X.X.X:6380,slaves=2,sentinels=3

info命令返回的信息中的 status 字段其实还有其他几种状态,仅列两个需要注意的如下:

  • s_down :Subjectively down(主观下线),即当前sentinel 认为 master 为”不可用”状态。
  • o_down :Objectively down(客观下线),即多个 sentinel 都认为 master 处于”s_down”状态,那么此时master将处于 o_down状态,即 master 已经被集群确定为”不可用”,将会开启 failover 重新选举新的 matser。

注意,Objectively down(客观下线)只适用于 master 节点, 对于其他类型的 Redis 节点, sentinel 在将它们判断为失效前不需要进行协商, 所以从服务器或者其他 sentinel 永远都不会达到客观下线的条件。

  • 本文作者: Marticles
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!