Redis Sentinel高可用部署

1. 前提条件

  1. 安装前确保所有待安装节点已经完成基础环境配置
  2. 本次安装 redis 版本为 6.2.7,安装包为:redis-6.2.7-amd64.tar.gz,为方便配置程序提前进行了编译并同时对配置文件做了部分修改,因此和默认安装包存在部分差别。

2. 集群环境和参数准备

  1. Redis安装目录设置为:/opt/redis-6.2.7-amd64
  2. Redis 持久化目录设置为:/data/redis
  3. 所有节点需要优化内核参数:开启内存过量提交、提高TCP listen队列长度

编辑/etc/sysctl.conf, 例如:vim /etc/sysctl.conf, 添加参数如下:

vm.overcommit_memory=1
net.core.somaxconn=4096
net.ipv4.tcp_max_syn_backlog=4096

保存然后执行 sysctl -p 生效。

集群共3个节点分别如下:

192.168.1.21   ecs21
192.168.1.22   ecs22
192.168.1.23   ecs23

节点角色如下:

       +----+
       | M1 |
       | S1 |
       +----+
          |
+----+    |    +----+
| R2 |----+----| R3 |
| S2 |         | S3 |
+----+         +----+

Configuration: quorum = 2

其中Redis有3个节点1个Master两个Replica节点,Sentinel必须是奇数个节点,例如:3、5、7等,至少3个才具备高可用性,因为Sentinel占用的资源不多所以在机器数量不多的情况下可以和Redis混合部署,并且可以管理多套Redis主从集群。

3. 安装与配置

安装思路是首先在其中1个节点上进行配置,配置成功后将安装包发送至其他节点,然后再稍微进行单独的配置即可。

首先选定ecs21节点上默认初始的Master进行配置,首先解压安装包到安装目录:

tar xvzf redis-6.2.7-amd64.tar.gz -C /opt/
cd /opt/redis-6.2.7-amd64

具体目录结构,参考Redis单节点配置中的说明。

3.1.配置Redis

首先在ecs21上编辑Redis的配置文件redis.conf主要内容如下:

# 默认为了安全只绑定回环地址
bind 127.0.0.1 -::1
# 由于配置主从 必须要绑定外部网卡
bind 0.0.0.0 ::

# 服务监听的端口号
port 6379

# pid文件 如果单机上有多个 redis 实例,不同的实例要单独修改
pidfile /var/run/redis_6379.pid
# 日志文件 如果单机上有多个 redis 实例, 不同的实例要单独修改
logfile "/var/log/redis_6379.log"

# RDB持久化的目录 默认为: ./ 务必修改正确
dir "/data/redis/"

# 用于ACL文件 默认为./users.acl 务必修改为实际的绝对路径
aclfile /opt/redis-6.2.7-amd64/users.acl

# 开启无盘复制
repl-diskless-sync yes
repl-diskless-sync-delay 5

# 可靠性配置
min-replicas-to-write 1
min-replicas-max-lag 10

# 副本同步的用户名和密码
masterauth <replica-pass>
masteruser <replica-user>

简单说一下上面新增的配置,参数repl-diskless-sync表示开启无盘复制,开启后可以提升复制的性能。

另外可靠性配置主要依靠min-replicas-to-writemin-replicas-max-lag这两个参数,这两个参数的配置是可选的,主要是为了可靠性考虑,参数具体表示至少有1个副本连接到当前Master才可以写入,并且数据同步的延迟不能超过10s,我们目前的情况正常会有2个副本连接到主节点,之所以这样配置是为了保证一定的稳定性,允许1个副本挂掉,但是如果全部副本挂掉时主节点也会阻止写入,否则当副本启动时同步的流量会比较大,所以至少保证要有1个副本正常才可以,同时写入的延迟不能超过10s,如果由于网络原因延迟过大也会禁止客户端写入,这样可以防止Redis主节点和副本之间的积压太大从而触发全盘复制,这样配置可以提供一些尽力而为的可靠性,上面的配置只对主节点的角色生效,对于副本节点则没有任何影响。

最后要使用独立的复制用户,这样复制节点通过该用户访问主节点,获取主节点最新的指令更新,并且同步执行,这个只是副本向主节点认证所需的密码,主节点相对于副本节点其实是具有root权限的,这个用户只需要添加psync replconf ping这3个非常少的权限即可。

3.2.配置Sentinel

同样也是在ecs21节点上先进行配置,编辑配置文件sentinel.conf主要配置如下:

port 26379
daemonize yes
# 日志文件位置
logfile "/var/log/redis-sentinel.log"

# 配置监控的Redis主从集群组
sentinel monitor mymaster 192.168.1.21 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 2

sentinel auth-user mymaster <sentinel-user>
sentinel auth-pass mymaster <sentinel-pass>

aclfile /opt/redis-6.2.7-amd64/sentinel-users.acl

sentinel sentinel-user <username>
sentinel sentinel-pass <password>

sentinel monitor mymaster 192.168.1.21 6379 2 这一行用于告诉Sentinel要监控的分组,名字为mymaster ,这个名字可以自己定义,包含大小写字母、数字以及._- 这些,其余的都不支持,然后后面跟上当前的Redis Master节点的ip和端口,最后的2表示法定人数,也就是有几个Sentinel认为该Master不可达,才开始启动故障转移,不过故障转移不仅和这个有关,还和Sentinel本身的法定人数有关,为了方便说明问题,我们假设有5个Sentinel,那么如果有2个Sentinel认为Master不可达,其中1个Sentinel将启动故障转移,对于5个Sentinel,最多允许两个故障,也就是说此时至少有3个Sentinel可达,才会真正执行故障转移操作,通常情况下后面这个数字一般是和Sentinel本身的法定人数保持一致,比如当前有3个Sentinel,那么至少需要2个Sentinel认为该Master不可达,而且Sentinel本身有2个是可达的,才启动故障转移,至少两个条件其中1个不具备,则不会启动故障转移,所以说如果在这里配置1个Sentinel是无效的,如果是两个节点配置两个Redis看似可以,但是由于Redis和Sentinel在同一个节点上,通常会同时失去联系,那么这个时候永远也达不到法定人数,同样无法实现故障转移,但是如果后面的数字设置为1,将会发生非常危险的状况,因为此时单侧将独立执行,出现“脑裂”的情况。

然后下面就是超时时间的配置了,同样需要指定监控组,例如down-after-milliseconds表示Sentinel认为服务不可达的时间,然后failover-timeout 表示故障恢复的超时时间,然后后面的parallel-syncs 表示节点被提升为Master后最多允许几个副本同时同步,如果这个值太高的话流量和主节点的压力会比较大,如果设置的比较低那么同步速度会很慢,当前我们设置为2

Sentinel可以灵活按照组的概念来配置要监控的主从集群,所以可以通过添加配置同时监控多个Redis主从组,而不需要启动多个Sentinel实例。

然后再往下的sentinel auth-user 以及sentinel auth-pass 表示Sentinel监控Redis所使用的用户名和密码,需要在所有Redis实例中都创建这个用户,同时分配最小权限。

然后下面的配置aclfile 和Redis的ACL是一致的,表示用户访问Sentinel本身所使用的用户文件,注意一定要修改为真实的路径,后面紧接着是Sentinel角色之间认证所使用的用户,可以自己创建,也可以使用默认的,默认情况下拥有超级权限,所以一定要设置高强度的密码,和Redis一样,超级用户只用于Sentinel内部之间通信,不可以提供给客户端使用,客户端需要使用受限的用户访问Sentinel。

本文中上面两个部分中提及的所有Redis和Sentinel用户,在Redis安装包中都已经完成了默认的配置,并保存至users.acl以及sentinel-users.acl中,在配置时需要以实际的用户和密码替换<>中对应的标识即可,要特别注意各个用户的用途和关系,不要配置混乱了。

3.3.配置Redis和Sentinel至所有节点

现在我们仅在3个节点的ecs21节点上完成了Redis和Sentinel的基本配置,接下来需要将安装目录同步至其他所有节点,这样所有节点的配置保持一致,不过为了方便后续使用systemd管理,我们首先修改好service文件中的安装目录。

编辑services/redis.service

[Unit]
Description=redis
After=network.target local-fs.target

[Service]
User=root
Group=root
Type=forking
ExecStart={{ redis_home }}/bin/redis-server {{ redis_home }}/redis.conf
TimeoutSec=90s
RestartSec=10s
Restart=always
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target

替换其中的{{ redis_home }}为当前实际的安装目录,如下:

[Unit]
Description=redis
After=network.target local-fs.target

[Service]
User=root
Group=root
Type=forking
ExecStart=/opt/redis-6.2.7-amd64/bin/redis-server /opt/redis-6.2.7-amd64/redis.conf
TimeoutSec=90s
RestartSec=10s
Restart=always
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target

然后保存,继续编辑service/redis-sentinel.service同样替换其中的{{ redis_home }}安装目录,如下:

[Unit]
Description=redis sentinel
After=network.target local-fs.target

[Service]
User=root
Group=root
Type=forking
ExecStart=/opt/redis-6.2.7-amd64/bin/redis-sentinel /opt/redis-6.2.7-amd64/sentinel.conf
TimeoutSec=90s
RestartSec=10s
Restart=always
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target

修改之后保存。

然后即可将当前的Redis安装目录同步至其他的节点,在当前ecs21节点上执行:

# 在ecs21上执行 注意目录后面一定不要加'/'
rsync -av /opt/redis-6.2.7-amd64 ecs22:/opt
rsync -av /opt/redis-6.2.7-amd64 ecs23:/opt

同步完成后,现在3个节点保持一致,由于默认情况下我们以ecs21作为Master角色,所以需要修改ecs22ecs23的Redis配置文件,告诉它们从ecs21进行复制,所以分别在ecs22ecs23上编辑配置文件redis.conf,添加配置如下:

replicaof 192.168.1.21 6379

修改完成后保存配置,注意需要在剩余的节点上完成修改,即ecs22ecs23

4.运行服务

依次在ecs21,ecs22,ecs23上启动Redis服务:

./bin/redis-server ./redis.conf

然后依次启动Sentinel服务:

./bin/redis-sentinel ./sentinel.conf

启动之后可以进入Sentinel客户端:

./bin/redis-cli -p 26379

然后进行用户认证后,即可查看主从的状态:

sentinel master mymaster

这样即可返回集群的信息,然后可以单独查看当前的Master节点:

sentinel get-master-addr-by-name mymaster

以及副本节点:

sentinel replicas mymaster

还可以查看其他Sentinel服务的运行状态:

sentinel sentinels mymaster

然后此时可以从Redis主节点进入后写入数据,查看副本节点成功同步过去,则说明复制运行正常,同时副本节点是read only的状态,不允许写入。

如果需要测试高可用的情况,只需要选择主节点的Redis服务kill掉,然后观察Sentinel和其他Redis的日志,在默认30s之后完成选举并切换,表示高可用的运行正常。

5.配置systemd接管Redis和Sentinel服务

同样和单节点一样为了方便使用Redis相关命令可以将bin目录添加至环境变量中:

# 所有机器都需要添加bin目录到PATH中
export PATH=$PATH:/opt/redis-6.2.7-amd64/bin

将上面的指令添加至/etc/profile或者~/.bashrc中均可。

然后将Redis服务添加至systemd管理,在所有节点依次执行下面的命令添加系统服务:

# 所有节点都需要执行
cd /opt/redis-6.2.7-amd64
cp services/*.service /usr/lib/systemd/system

执行后需要先停止掉手动启动的Redis服务,然后重新使用systemd启动:

# 在所有节点上启动Redis服务
systemctl start redis.service
# 查看状态
systemctl status redis.service
# 在所有节点上启动Sentinel服务
systemctl start redis-sentinel.service
systemctl status redis-sentinel.service

启动后可以连接Sentinel或者查看日志是否正常,最后可以在所有节点上设置Redis和Sentinel服务开机自动启动:

# 在所有节点上分别执行
systemctl enable redis.service
systemctl enable redis-sentinel.service

这样Redis和Sentinel服务就可以根据系统自动启动了。

Reference:

  1. https://redis.io/docs/manual/sentinel/