Cache-Redis-02-Redis-Master-Slave-Sentinel
方案
1主2从3哨兵
主可读可写,从只读,哨兵监听主宕机,进行Failover 故障迁移,将原从节点变为主节点,原主节点恢复后变为从节点
优点
简单
服务器数量要求低
缺点
可能丢失部分未同步的数据
不能负载均衡
前置条件
- CentOS 7.9.2009
- 3台以上单数服务器
安装
主从节点安装Redis
参照非集群方式安装Redis
从节点配置Replica副本
从节点从主节点执行数据复制,以便保持两个节点的Redis服务的数据一致
以下操作所有从服务器都需要执行
配置从节点是主节点的副本
sed -i 's/^# slaveof <masterip> <masterport>/slaveof <MasterRedisIP> <MasterRedisPort>/' /etc/redis.conf
# 以下操作所有服务器都需要执行
# 主节点的密码
sed -i 's/^# masterauth <master-password>/masterauth <MasterPassword>/' /etc/redis.conf
# 重启redis服务,使配置生效
systemctl restart redis
验证复制
# 主从节点验证角色
ROLE
# 主节点写入数据
set key value
# 从节点读取数据
get key
主从节点配置Sentinel哨兵
Redis Sentinel可以通过心跳检测的方式监视多个主服务器以及它们属下的所有从服务器,并在某个主服务器下线时自动对其实施故障转移
备份原哨兵配置文件
cp /etc/redis-sentinel.conf /etc/redis-sentinel-origin.conf
以下操作所有服务器都需要执行
# 以下命令2选1
# 1/[2] 设置绑定IP,内网IP
# 注意不要设置127.0.0.1,否则其它哨兵会连接失败,导致哨兵之间不能构成网络,最终故障转移失败
# 如果要设置127.0.0.1 需要同时设置 sentinel announce-ip <IPAddress>为具体内网地址
# 可以设置0.0.0.0 或者 具体的内网IP
sed -i 's/^# bind 127.0.0.1 192.168.1.1/bind <IPAddress>/' /etc/redis-sentinel.conf
# 2/[2] 设置非保护模式
sed -i 's/^# protected-mode no/protected-mode no/' /etc/redis-sentinel.conf
# 哨兵监听主节点,从节点会在连上主节点上后获取
# <MasterRedisName>是为主服务取的名字,哨兵的各种命令需要该名字,推荐使用mymaster的名字
# <MasterRedisName>可用字符[a-zA-Z.-_]
# <MasterRedisIP>和<MasterRedisPort>为主节点的IP和端口
# 只要有<Quorum>个Sentinel认为<MasterRedisName>主服务器下线了,
# <Quorum>推荐设置为节点数n/2+1,即一半以上(不含一半)
# 注意<Quorum>配置不影响Sentinel自动故障转移,自动故障转移需要一半以上的节点投票
sed -i 's/^sentinel monitor mymaster 127.0.0.1 6379 2/sentinel monitor <MasterRedisName> <MasterRedisIP> <MasterRedisPort> <Quorum>/' /etc/redis-sentinel.conf
# 配置哨兵连接主节点时的密码
sed -i 's/^# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd/sentinel auth-pass <MasterRedisName> <MasterRedisPassword>/' /etc/redis-sentinel.conf
# 注意默认重新选主需要30s,可通过以下命令修改
# 注意如果<MasterRedisName> 不是mymaster,需要执行以下命令
# sed -i 's/^sentinel down-after-milliseconds mymaster 30000/sentinel down-after-milliseconds <MasterRedisName> 30000/' /etc/redis-sentinel.conf
先启Master的哨兵,再启动Slave的哨兵
# 启动哨兵服务
systemctl start redis-sentinel
# 验证哨兵服务正常启动
systemctl status redis-sentinel
# 设置哨兵服务开机自动启动
systemctl enable redis-sentinel
# 验证哨兵服务开机自动启动设置成功
systemctl is-enabled redis-sentinel
验证哨兵
redis-cli -p 26379
# 哨兵相关信息
127.0.0.1:26379> info sentinel
# 主从节点相关信息
127.0.0.1:26379> sentinel masters
# 查看当前主节点IP和端口
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster
防火墙
# 增加哨兵通信端口的例外规则
# 防火墙允许外网对26379端口访问
firewall-cmd --permanent --zone=public --add-port=26379/tcp
firewall-cmd --reload
测试
模拟Redis崩溃
# 主节点执行命令 模拟故障
redis-cli
# 输入密码
127.0.0.1:6379> AUTH <RedisPassword>
# DEBUG segfault和DEBUG sleep 30两个命令请2选1
# 模拟Redis不可用30s,过后自动恢复
127.0.0.1:6379> DEBUG sleep 60
# 命令执行一个非法的内存访问从而模拟Redis崩溃
# 仅在开发时用于 BUG 调试,执行后需要重启服务
127.0.0.1:6379> DEBUG segfault
# 查看哨兵日志
tail -f /var/log/sentinel.log
# 其它节点执行以下命令
redis-cli
127.0.0.1:6379> AUTH <RedisPassword>
127.0.0.1:6379> INFO Replication
redis-cli -p 26379
# 查询哨兵信息
127.0.0.1:26379> INFO Sentinel
# 查看当前主节点IP和端口
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster
# 检测当前可达的Sentinel节点总数是否达到<quorum>的个数
127.0.0.1:26379> SENTINEL ckquorum mymaster
# 如果执行的是DEBUG segfault则需要重启原主节点Redis服务
# systemctl restart redis
# 确认redis服务已启动成功
# systemctl status redis
# 再次检查相关信息是否符合预期
# 执行13-24行相关命令
手动故障转移
# 手动故障转移
redis-cli -h <IPAddress> -p 26379
# 强制执行failover故障转移,不用经过其他sentinel节点的同意。
127.0.0.1:26379>SENTINEL failover mymaster
# 查看当前master,主节点
# 查看当前主节点IP和端口
127.0.0.1:26379> SENTINEL get-master-addr-by-name mymaster
关闭服务
# 关闭主节点Redis服务
systemctl stop redis
redis-cli -h <IPAddress> -p 26379
# 验证原从节点Redis服务变为主节点,且有disconnected标志(第10个字段)
<IPAddress>:26379> SENTINEL slaves mymaster
# 恢复原主节点Redis服务
systemctl start redis
# 验证原主节点Redis服务启动后变为从节点,且无disconnected标志(第10个字段)
<IPAddress>:26379> SENTINEL slaves mymaster
重启服务器
虚拟机会测试失败,因为重启太快就恢复了
物理机估计会成功
# 谨慎操作,会重启服务器
# reboot
redis-cli -h <IPAddress> -p 26379
# 验证原从节点Redis服务变为主节点,且有s_down标志(第10个字段)
<IPAddress>:26379> SENTINEL slaves mymaster
# 等待重启成功
# 验证原主节点Redis服务启动后变为从节点,且没有s_down标志(第10个字段)
<IPAddress>:26379> SENTINEL slaves mymaster
关闭服务器
# 谨慎操作,会关闭服务器
# shutdown now
redis-cli -h <IPAddress> -p 26379
# 验证原从节点Redis服务变为主节点,且为s_down标志(第10个字段)
<IPAddress>:26379> SENTINEL slaves mymaster
# 开启服务器
# 验证原主节点Redis服务启动后变为从节点,且没有s_down标志(第10个字段)
<IPAddress>:26379> SENTINEL slaves mymaster
调试
# 查看哨兵日志
tail -f /var/log/redis/sentinel.log
常用命令配置
# 取消成为从节点,即不复制任何节点的数据了
SLAVEOF no one
# 查看当前节点角色
ROLE
# 主节点执行ROLE示例
# 127.0.0.1:6379> ROLE
# 1) "master" --这是一个主服务器
# 2) (integer) 155 --它的复制偏移量为155
# 3) 1) 1) "127.0.0.1" --第1个从服务器的IP地址为127.0.0.1
# 2) "12345" --这个从服务器的端口号为12345
# 3) "155" --它的复制偏移量为155
# 2) 1) "127.0.0.1" --第2个从服务器的IP地址为127.0.0.1
# 2) "10086" --端口号为10086
# 3) "155" --复制偏移量为155
# 从节点执行ROLE示例
# 127.0.0.1:12345> ROLE
# 1) "slave" --这是一个从服务器
# 2) "127.0.0.1" --主服务器的IP地址
# 3) (integer) 6379 --主服务器的端口号
# 4) "connected" --主从服务器已经进入在线更新状态
# 5) (integer) 1765 --这个从服务器的复制偏移量为1765
# 状态类型及含义
# "none":主从服务器尚未建立连接。
# "connect":主从服务器正在握手。
# "connecting":主从服务器成功建立了连接。
# "sync":主从服务器正在进行数据同步。
# "connected":主从服务器已经进入在线更新状态。
# "unknown":主从服务器连接状态未知。
# 配置无盘复制,不会在主节点进行写入RDB文件,但是会在从节点写入RDB文件
repl-diskless-sync yes
# 降低数据不一致情况出现的概率
# 主服务器只会在从服务器的数量大于等于min-replicas-to-write选项的值,
# 并且这些从服务器与主服务器最后一次成功通信的间隔不超过min-replicas-max-lag选项的值时
# 才会执行写命令
min-replicas-to-write <numbers>
min-replicas-max-lag <seconds>
# 查看哨兵信息
info sentinel
# 展示所有被监控的主节点状态以及相关的统计信息
sentinel masters
# 展示指定<master name>的主节点状态以及相关的统计信息
sentinel master <master name>
# 展示指定<master name>的从节点状态以及相关的统计信息
sentinel slaves <master name>
# 展示指定<master name>的Sentinel节点集合(不包含当前Sentinel节点)
sentinel sentinels <master name>
# 返回指定<master name>主节点的IP地址和端口
sentinel get-master-addr-by-name <master name>
# 重置所有名字和给定模式 pattern 相匹配的主服务器
SENTINEL reset <pattern>
# 取消当前Sentinel节点对于指定<master name>主节点的监控
sentinel remove <master name>
# 通过命令的形式来完成Sentinel节点对主节点的监控
sentinel monitor <master name> <ip> <port> <quorum>
# 动态修改Sentinel节点配置选项
# 只对当前哨兵起效
SENTINEL set <master-name> <option> <value>
# Sentinel节点之间用来交换对主节点是否下线的判断
# 根据参数的不同,还可以作为Sentinel领导者选举的通信方式
sentinel is-master-down-by-addr
# Redis>=5.0以上,显示Master节点下的replicas节点和状态。
SENTINEL REPLICAS <MasterName>
专业术语
术语 | 全称 | 含义 |
---|---|---|
Failover | 故障转移 | 主服务发生故障宕机下线时,将主转移到原来的某一个从服务上以便继续提供服务 |
常见问题FAQ
Q1: 主服务宕机重新上线后,会如何?
A1:Sentinel在对下线的主服务器实施故障转移之后,仍然会继续对它进行心跳检测,当这个服务器重新上线的时候,Sentinel将把它转换为当前主服务器的从服务器。
Q2: 选主的过程是如何的?
A2: 当Sentinel需要在多个从服务器中选择一个作为新的主服务器时,首先会根据以下规则从候选名单中剔除不符合条件的从服务器:
1)否决所有已经下线以及长时间没有回复心跳检测的疑似已下线从服务器。
2)否决所有长时间没有与主服务器通信,数据状态过时的从服务器。
3)否决所有优先级为0的从服务器。
然后根据以下规则,在剩余的候选从服务器中选出新的主服务器:
1)优先级最高的从服务器获胜。
2)如果优先级最高的从服务器有两个或以上,那么复制偏移量最大的那个从服务器获胜。
3)如果符合上述两个条件的从服务器有两个或以上,那么选出它们当中运行ID(运行ID是服务器启动时自动生成的随机ID,这条规则可以确保条件完全相同的多个从服务器最终得到一个有序的比较结果)最小的那一个
Q3: 不同服务器上执行SENTINEL get-master-addr-by-name mymaster 得到的主服务器不一致,即脑裂了怎么办?
A3: 需要执行以下命令进行手动故障转移,使集群的主服务器一致
redis-cli -h <IPAddress> -p 26379
# 对指定<master name>主节点进行强制故障转移
<IPAddress>:26379> sentinel failover <master name>
参考
《Redis使用手册》--黄健宏