Redis之主从复制(Sentinel)
基于Redis自身的主从复制模式,一旦Master挂掉,那么需要手动将Slave节点晋升为Master,而且还需要通知应用方更新Master节点地址,所以这种方式肯定不能接受。所以为了解决这个Redis高可用问题,Redis哨兵即Sentinel诞生。
一Sentinel概念
1.1 主从复制
Redis主从复制模式,可以将主节点数据改变同步给从节点,这样从节点就起到了2个作用:备份和扩展主节点读的能力。
问题:
# 主节点出现问题,需要手动切换从节点为主节点,你并且通知客户端主节点变化
# 主节点写的能力受单机限制
# 主节点存储能力受单机限制
1.2Sentinel的高可用性
当主节点出现故障的时候,Redis Sentinel能够自动完成故障发现和故障转移。并通知应用方从而实现真正的高可用。
Redis Sentinel 是一个分布式架构,其中包含 若干个Sentinel节点和Redis数据节点,每一个Sentinel会对数据节点和其他Sentinel节点进行监控,当他发现节点不可达时,会对节点做下线标识。如果被标识的是主节点,他还会和其他节点Sentinel节点协商,当大多数Sentinel节点都认为主节点不可达的时候,会选举一个Sentinel节点来完成自动故障转移的工作,并且会将这个变化实时通知给Redis应用方。整个过程是自动的,完全不需要人工来干预。
注意: Sentinel也是Redis节点,只不过他不是用于存储数据。
1.3Sentinel的功能
# 监控: Sentinel节点会定期检测其他Sentinel节点和Redis数据节点
# 通知: Sentinel会将故障转移的结果通知给应用方
# 主节点故障转移: 选出新主节点,然后维护后续正确的主从关系
二Sentinel 安装部署
2.1 部署拓扑图
2.2 部署Redis数据节点
2.2.1 配置主节点
port 6379
bind 192.168.1.201
daemonize yes
pidfile /opt/app/sentinel/master/redis.pid
logfile /opt/app/sentinel/master/logs/redis.log
appendonly yes
dir /opt/app/sentinel/master/data
启动主节点:bin/redis-servercon/redis.conf
2.2.2 配置从节点
Slave-01配置:
port 6379
bind 192.168.1.202
daemonize yes
pidfile /opt/app/sentinel/slave1/redis.pid
logfile /opt/app/sentinel/slave1/logs/redis.log
appendonly yes
dir /opt/app/sentinel/slave1/data
slaveof 192.168.1.201 6379
Slave-02配置:
port 6379
bind 192.168.1.203
daemonize yes
pidfile /opt/app/sentinel/slave2/redis.pid
logfile /opt/app/sentinel/slave2/logs/redis.log
appendonly yes
dir /opt/app/sentinel/slave2/data
slaveof 192.168.1.201 6379
启动从节点
bin/redis-server conf/redis.conf
2.2.3 确认主从关系
bin/redis-cli -h 192.168.1.201 -p 6379 inforeplication
检查主从关系是否确立
2.3 部署Sentinel节点
# monitor 指定需要监控主节点
sentinel monitor <master-name> <ip><redis-port> <quorum>
master-name:指定的master名字
ip: 要监听的数据主节点节点IP地址
redis-port:要监听的数据主节点端口
quorum:为确认这个主服务器已下线所需要的最少Sentinel数量
# down-after-milliseconds 指定了 Sentinel 认为服务器已经断线所需的毫秒数
sentinel down-after-milliseconds<master-name> <milliseconds>
# failover-timeout 指定了故障转移的超时时间,
sentinel failover-timeout <master-name><milliseconds>
# parallel-syncs 指定了在执行故障转移时, 最多可以有多少个从服务器同时对新的主服务器进行同步
sentinel parallel-syncs mymaster 1
2.3.1 配置和启动三个Sentinel节点
Sentinel1节点:
port 26379
bind 0.0.0.0
dir "/opt/app/sentinel/sentinel1/data"
daemonize yes
pidfile /opt/app/sentinel/sentinel1/sentinel.pid
logfile"/opt/app/sentinel/sentinel1/logs/sentinel.log"
sentinel monitor mymaster 192.168.1.201 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
Sentinel2节点:
port 26379
bind 0.0.0.0
dir "/opt/app/sentinel/sentinel2/data"
daemonize yes
pidfile /opt/app/sentinel/sentinel2/sentinel.pid
logfile "/opt/app/sentinel/sentinel2/logs/sentinel.log"
sentinel monitor mymaster 192.168.1.201 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
Sentinel3节点:
port 26379
bind 0.0.0.0
dir "/opt/app/sentinel/sentinel3/data"
daemonize yes
pidfile /opt/app/sentinel/sentinel3/sentinel.pid
logfile "/opt/app/sentinel/sentinel3/logs/sentinel.log"
sentinel monitor mymaster 192.168.1.201 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
查看sentinel信息
bin/redis-cli -h 192.168.1.201 -p 6379 infosentinel
# 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=192.168.1.201:6379,slaves=2,sentinels=3
2.3.2 配置优化
# sentinel master
需要监视的主节点IP和端口以及quorum,quorum这个表示多少个sentinel节点认为主节点已经挂掉了,才视为主节点下线,即客观下线; 同时quorum还跟sentinel节点的leader选举有关系,至少要max(quorum,sentinel节点数/2 + 1)个sentinel节点参加选举,才能选举出leader,从而进行故障转移。
# sentinel down-after-milliseconds
每一个sentinel节点都会向主节点,从节点和其他sentinel节点1秒钟ping一次。在down-after-milliseconds毫秒内没有进行回复,sentinel节点就会判定该节点失败,这个行为叫做主观下线。
# sentinel parallel-syncs
当sentinel领导者开始进行故障转移的时候,选出新的主节点,原来的从节点会向新的主节点发起复制操作,parallel-syncs就是用来限制在一次故障转移之后,每次向新的主节点同时发起复制操作节点个数。如果这个值较大, 虽然一般不会阻塞主节点,但是会给网络和磁盘IO带来开销。
# sentinel failover-timeout
故障转移超时时间
# sentinel auth-pass
如果sentinel监控的主节点设置了密码,sentinel auth-pass配置通过添加主节点的密码,防止sentinel节点对主节点无法监控。
# sentinel notification-script
在故障转移期间,当一些警告级别的sentinel事件发生时,会触发对应的脚本,并向脚本发送相对应的事件参数。
2.4 如何监控多个主节点
sentinel monitor master1 192.168.1.201 6379 2
sentinel down-after-milliseconds master1 30000
sentinel failover-timeout master1 180000
sentinel parallel-syncs master1 1
sentinel monitor master2 192.168.1.202 6379 2
sentinel down-after-milliseconds master2 30000
sentinel failover-timeout master2 180000
sentinel parallel-syncs master2 1
2.5 部署技巧
2.4.1sentinel节点尽量不要部署在一台物理机上
2.4.2sentinel节点至少三个而且是奇数
2.4.3 如果是同一个业务的多个主节点,可以使用一套sentinel,否则就使用多套sentinel
三Sentinel 客户端
无论哪一种编程语言的客户端,如果需要正确的连接Redis Sentinel,必须有Sentinel节点集合和主节点参数。
3.1Redis Sentinel 客户端基本实现原理
实现一个Redis Sentinel客户端的基本步骤如下:
# 遍历sentinel节点集合获取一个可用的sentinel节点,从任意一个sentinel节点获取主节点信息都是可以的
# 通过sentinel get-master-addr-by-name master-name获取主节点信息
# 验证当前获取的主节点是真正的主节点,防止故障转移期间的主节点变化
# 保持和sentinel节点的联系,时刻获取关于主节点相关的信息
3.2Java操作Redis Sentinel
private static JedisSentinelPoolgetSentinelPool(String
masterName,Set<String>
sentinels) {
if (StringUtils.isBlank(masterName) ||
CollectionUtils.isEmpty(sentinels)) {
return null;
}
JedisPoolConfig config
= new JedisPoolConfig();
config.setMaxTotal(1024);
config.setMaxIdle(200);
config.setMaxWaitMillis(1000);
return new JedisSentinelPool(masterName,sentinels,config);
}
四 Sentinel实现原理
4.1 三个定时监控任务
Redis通过三个定时任务完成对各个节点的监控:
4.1.1每隔10秒,每个Sentinel节点会向Master节点和Slave节点发送方info命令获取最新的拓扑结构,比如:
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.1.202,port=6379,state=online,offset=67874,lag=1
slave1:ip=192.168.1.203,port=6379,state=online,offset=68015,lag=0
对上述结果解析就可以找到相应的从节点。
该定时任务的作用:
# 向主节点发送info命令获取从节点信息,所以sentinel不需要显示配置监控从节点
# 当有新的从节点加入,可以立刻感知出来
# 节点不可达,或者故障转移后,可通过info命令实时更新拓扑信息
4.1.2 每隔2秒,每一个sentinel 节点会向Redis数据节点的__sentinel__:hello 频道上发送该sentinel节点对于主节点的判断以及当前sentinel节点的信息,同时每一个sentinel节点也会订阅该频道
4.1.3 每隔1秒,每一个sentinel节点会向主节点,从节点,其余sentinel节点发送一条ping命令,做一次心跳检测,来确认这些节点当前是否可达
4.2 主观下线和客观下线
4.2.1主观下线
当sentinel对主节点,从节点和其他sentinel节点发送ping命令进行心跳检测,如果超过down-after-milliseconds没有进行回复,Sentinel节点就会判定该节点失败,这个行为叫做主观下线
4.2.2 客观下线
当sentinel主观下线是主节点的时候,该sentinel会通过sentinel is-master-down-by-addr,命令向其他sentinel节点询问对主节点的判断,当超过quorum个数的sentinel节点认为主节点确实存在问题,这时候sentinel节点会做出客观下线的决定
4.3 领导者Sentinel节点的选举
当sentinel节点对于主节点已经做了客观下线,也不是立刻就进行故障转移,在转移还需要选举一个leader专门用来处理故障转移。Redis使用Raft算法实现领导者选举。
大致过程如下:
# 每一个在线的sentinel节点都有资格成为领导者,当它确认主节点主观下线的时候,会向其他节点发送sentinel is-master-down-by-addr命令,要求将自己设置为leader
# 收到命令的sentinel节点,如果没有同意过其他其他sentinel的节点is-master-down-by-addr命令,将同一该请求,否则拒绝
# 如果该sentinel发现自己的票数已经大于等于max(quorum,sentinel节点数/2+1),那么它将成为领导者
# 如果此过程没有选举出leader,将进入下一次选举
所以我们也可以这样理解,谁最先确认主节点客观下线,谁最有可能成为Leader.
4.4 故障转移
4.4.1 从从节点列表选择一个节点作为新的主节点,选择方法如下:
# 过滤不健康的从节点
# 选择slave-priority最高的,如果存在即返回,不存在就继续
# 选择复制偏移量最大的从节点,如果存在即返回,不存在就继续
# 选择runid最小的从节点
4.4.2 sentinelleader会对前一步选择的从节点执行slaveof no one命令,让其成为主节点
4.4.3sentinel leader向剩余的从节点发送命令,让他们成为新的主节点的从节点,复制规则和parallel-sync参数有关系
4.4.4sentinel节点集合会将原来的主节点更新为从节点,并保持对其关注,当起恢复后命令其去复制新的主节点
五Sentinel开发与运维
5.1 节点下线
临时下线:暂时关掉节点,之后会重新启动
永久下线:关闭之后永远不会再使用,有时候还需要做一些清理工作,比如等
5.1.1 主节点下线
sentinel failover <master name>
5.1.2 从节点和sentinel节点
如果使用了读写分离,下线从节点需要保证应用方可以感知从节点的下线变化,并把读请求路由到其他节点。
5.2 节点上线
5.2.1 添加从节点
有时候比如只有一台节点的情况下,想使用主从,支撑故障转移;或者使用的读写分离,不能支撑应用方的流量
slaveof <masterip> <masterport> 的配置,使用redis-server启动即可,他将被 sentinel节点自动发现。
5.2.2 添加sentinel节点
当前sentinel节点数量不够,无法达到健壮性的要求或者无法达到票数;或者之前的sentinel节点需要下线
添加配置然后正常启动sentinel即可,被其余的sentinel节点自动发现