Redis之主从复制(Sentinel)

数据库 waitig 474℃ 百度已收录 0评论

基于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节点自动发现


本文由【waitig】发表在等英博客
本文固定链接:Redis之主从复制(Sentinel)
欢迎关注本站官方公众号,每日都有干货分享!
等英博客官方公众号
点赞 (0)分享 (0)