Redis Sentinel(哨兵)

Redis sentinel是redis官方推荐的redis高可用(HA)解决方案。sentinel主要的功能包括:

  • 监控(Monitoring),sentinel时刻监控着redis master-slave是否正常运行
  • 通知(Notification),sentinel可以通过API来通知管理员,被监控的redis master-slave出现了问题
  • 自动故障转移(Automatic failover),当redis master出现故障导致不可用状态,sentinel会进行故障转移,将slave提升为新的master,将其它slave将重新配置使用新的master同步,并使用redis的服务器应用程序在连接时使用新的地址连接
  • 配置提供者(Configuration provider),sentinel作为在集群中的权威来源,客户端连接到sentinel来获取服务当前redis主节点的地址和其它信息。当故障转移发生时,sentinel会报告新的地址。

配置哨兵服务

主从配置 略。主从安装配置可参考Redis Replication

哨兵参数配置

1
2
3
4
5
6
7
8
9
daemonize yes
port 26379
dir "/service/redis/sentinel"
sentinel deny-scripts-reconfig yes
sentinel monitor redis_shard1 10.0.139.163 26379 2
sentinel down-after-milliseconds redis_shard1 30000
sentinel parallel-syncs redis-shard1 1
sentinel failover-timeout redis_shard1 30000
sentinel auth-pass redis_shard1 Abcd123#

参数说明

参数 说明
port sentinel端口
dir sentinel数据目录
sentinel monitor [master-name] [ip] [port] [quorum] 定期监控主节点,master-name为主节点别名,quorum为判断主节点不可达需要的票数,例如设置为2则代表至少要有两个sentinel节点认为主节点不可达,通常建议sentinel节点数的一半加1
sentinel down-after-milliseconds [master-name] [time] 每个sentinel通过定期ping来判断redis和其它sentinel节点是否可达,如果超过down-after-milliseconds配置的时间没有有效回复则认为节点不可达
sentinel parallel-syncs [master-name] [nums] 当故障转移完成时,从节点会向新的主节点发起同步,parallel-sync用于限制每次向新的主节点发起复制的从节点个数
sentinel failover-timeout [master-name] [time] 故障转移超时时间,如果故障转移失败,则下次再对主节点做故障转移的起始时间为failover-timeout的2倍
sentinel auth-pass [master-name] [password] 设置主节点的认证密码
sentinel notification-script [master-name] [script-path] 故障转移期间,当一些告警级别的sentinel事件发生,会触发执行指定脚本,并向脚本发送相应的事件参数
sentinel client-reconfig-script [master-name] [scirpt-path] 在故障转移结束后触发指定脚本,并向脚本发送故障转移结果的相关参数

Sentinel能够通过主节点获取到从节点和其它sentinel节点的信息,并写入sentinel参数文件,无需手动添加。sentinel同时也支持监控多个主节点,通过master-name区分即可。

启动哨兵服务

1
$ redis-sentinel /etc/redis/sentinel.conf

查看哨兵状态

1
2
3
4
5
$ redis-cli -p 26379
## 查询主节点信息
127.0.0.1:26379> sentinel master redis_shard1
## 查询从节点信息
127.0.0.1:26379> sentinel slaves redis_shard1

Jedis连接Redis Sentinel

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Jedis jedis = null;
try {
  jedis = jedisSentinelPool.getResource();
  // do someting
} catch (Exception e) {
  logger.error(e.getMessage(),e);
} finally {
  if (jedis != null) {
    jedis.close()
  }
}

常用sentinel命令

查看sentinel节点信息

1
127.0.0.1:26379> sentinel sentinels redis_shard1

查看主节点IP和端口

1
127.0.0.1:26379>  sentinel get-master-addr-by-name redis_shard1

重置配置

1
127.0.0.1:26379> sentinel reset redis_shard1

强制故障转移

1
127.0.0.1:26379> sentinel failover redis_shard1

检查sentinel节点数量是否达到quorum

1
127.0.0.1:26379> sentinel ckquorum redis_shard1

将sentinel配置强制刷到磁盘上

1
sentinel flushconfig

取消监控(仅对当前sentinel节点有效)

1
sentinel remove redis_shard1

动态修改sentinel配置

和普通的Redis数据节点一样,sentinel也支持动态修改参数配置

1
sentinel set <param> <value>

需要注意的是:

  1. sentinel set只对当前sentinel节点有效,建议统一设置
  2. sentinel set执行成功后会立即更新配置文件

Sentinel工作原理

三个定时任务

Sentinel内部包含三个定时任务来监控判定节点不可达:

  • 每10秒每个sentinel会对master、slave发送info命令
  • 每2秒每个Sentinel节点会向Redis数据节点的__sentinel__:hello频道上发送该sentinel节点对主节点的判断以及sentinel节点的信息,同时每个sentinel节点也会订阅该频道,用于sentinel交换信息。
  • 每1秒sentinel对其它sentinel和redis实例进行PING操作,相当于心跳检测,判断节点是否可达。

主观下线和客观下线

主观下线(SDOWN)指单个sentinel对节点做出的下线判断,节点在down-after-millseconds给定的时间内,没有返回sentinel发送的ping命令或者返回错误,那么sentinel将节点标记为主观下线,修改其flags状态为SRI_S_DOWN。

客观下线(ODOWN)指多个sentinel对同一节点做出SDOWN判断,并且通过sentinel is-master-down-by-addr命令相互交流后,超过quorum则确认节点下线,随即进行failover切换

当单个sentinel对master节点做出主观下线的判断,会通过sentinel is-master-down-by-addr <current_epoch> 来询问其它监视的sentinel,让它们也做出判断。其中ip为master地址,port为master端口,current_epoch为sentinel的纪元,runid等于*表示检测服务下线状态,sentinel id则表示用来选举领头sentinel。当其它sentinel接收到消息并做出回复,回复包含:down_state(1表示下线,0表示在线),leader_runid(领头sentinel id),leader_epoch(领头sentinel 纪元)。如果做出主观判断的sentinel数量超过quorum指定的数量则判断master节点客观下线,进行failover。

领头者选举 当处于客观下线时,Redis通过Raft算法,多个sentinel进行协调,选出一个领头的sentinel,对数据节点进行failover操作。领头者遵循以下原则:

  • 所有sentinel都有被选举的资格
  • 所有sentinel有且只有一次选举的机会,一旦选定领头者,则不能修改
  • 领头者选择为先到先得的原则,即一旦选定则其它的请求都被拒绝
  • 每个发现节点服务客观下线的sentinel,都会参加领头者的选举
  • 当一个sentinel向其它sentinel发送is-master-down-by-addr命令时,runid为sentinel id时,则表示参加领头者选举
  • 其它sentinel回复的leader_runid和leader_epoch为sentinel的id,则表示同意选择其为领头者
  • 一个sentinel被max(quorum,num(sentinels)/2+1)以上的sentinel选举为领头者,则其就作为领头者
  • 如果规定时间内没有选举出,则暂停一段时间再次进行选举

故障转移

在选举出领头者后,由领头者负责故障转移,它会从节点中选出一个新的主节点,选择方法主要是

  • 过滤主观下线、5秒内没有回复PING响应、与主节点失联超过down-after-milliseconds*10秒
  • 选择slave-priority优先级较高的从节点
  • 选择复制偏移量最大的从节点
  • 选择runid最小的从节点

在完成选择后,sentinel会对新主节点执行slave no one让其成为主节点。随后sentinel领导者会向其它的从节点发送命令,让他们成为新主节点的复制从节点。下线的节点在恢复后将让它去复制新的主节点。

版本号 当一个sentinel被授权后,它将会获得客观下线的master的一份最新版本号,当failover结束这个版本号将会被用于最新的配置。每次failover都会附带一个独一无二的版本号,当第一次failover失败后,将会在一定时间内进行重新failover,这个由failover_timeout参数控制

广播 一个failover要想成功,sentinel必须能够向候选为master的slave节点发送SLAVEOF NO ONE命令,然后能够通过INFO查看最新的配置信息。当一个slave选举为master并发送SLAVEOF NO ONE后,即使其它slave还未配置到新master上,failover也被视作成功,最后sentinel将更新最新配置。新配置都将通过__sentinel__:hello的发布订阅渠道去广播最新配置信息。

参考信息

1. Redis Sentinel Documentation 2. Redis哨兵模式(sentinel)学习 3. 《Redis开发与运维》

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus