使用 Redis Sentinel 实现自动故障转移

这篇文章是从我自己的博客文章中抽取出来的与Redis Sentinel相关的内容。如果有追加内容,我会在博客上继续写。 “Redis监控/分析工具综述” http://rest-term.com/archives/3045/

哨兵模式的 Redis

这是一个管理服务器(redis-sentinel),它在Redis官方项目中进行开发,提供Redis服务器的存活监控/通知和自动故障转移功能。它从v2.4.16或2.6.0-rc6及更高版本开始可用。我们将参考官方文档进行操作验证。

    • 環境:

 

    CentOS 5.9 (x86_64), Redis 2.6.10

构成

在这里,我们将使用两个主机,组成2个进程的从属节点,并使用3个进程的哨兵节点进行试验。

    • Master db0:6379

 

    • Slave db0:6380, db1:6379

 

    Sentinel db0:26379, db0:23680, db1:26379

设定

# port <sentinel-port>
port 26379
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster db0 6379 2
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 5000
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 900000
# sentinel can-failover <master-name> <yes|no>
sentinel can-failover mymaster yes
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1

以下是关于每个设置项目的表格。 Sentinel通过所谓的Quorum-Based投票方法来监视集群。多个Sentinel监视Master,当其中超过阈值数量的Sentinel检测到Master宕机时,将启动故障转移处理。

設定項目概要monitorMasterのホストとポートおよび状態がODOWN(objectively down)に移行するための定足数(quorum)down-after-millisecondsMaster/Slaveのダウン検知後、状態がSDOWN(subjectively down)に移行するまでの時間(ms)failover-timeoutフェイルオーバー処理のタイムアウト(ms)can-failoverフェイルオーバー処理が実行可能か(yes/no)parallel-syncsSlaveをMasterに昇格させた後、いくつのSlaveと同期させるか

Sentinel将对Master和Slave进行生死状态监测,但只有Master的状态转为ODOWN时请注意。将can-failover设置为no启动的Sentinel进程不会执行故障转移过程(将由其他Sentinel负责),只进行自身的宕机检测和投票处理。

开动

在启动Sentinel之前,请确保复制正在运行。

redis db0:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:db0,6380,online
slave1:db1,6379,online

接着启动三个Sentinel进程。

$ redis-sentinel /etc/redis/sentinel.conf
## または redis-server をsentinelモードで起動する
$ redis-server /etc/redis/sentinel.conf --sentinel

在日志中可以确认与每个 Slave 和 Sentinel 进行了连接。

[19069] 14 May 16:30:31.909 * +slave slave db1:6379 db1 6379 @ mymaster db0 6379
[19069] 14 May 16:30:31.909 * +slave slave db0:6380 db0 6380 @ mymaster db0 6379
[19069] 14 May 16:30:38.320 * +sentinel sentinel db0:26380 db0 26380 @ mymaster db0 6379
[19069] 14 May 16:30:39.655 * +sentinel sentinel db1:26379 db1 26379 @ mymaster db0 6379

此外,在Sentinel启动后,您可以使用INFO命令来查看与Sentinel相关的信息。

redis db0:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
master0:name=mymaster,status=ok,address=db0:6379,slaves=2,sentinels=3

只需查看底部项目,即可监视Sentinel进程本身。

为了验证故障转移处理的操作,此处将关闭主服务器。

redis db0:6379> shutdown

ログにてフェイルオーバー処理の進捗を確認できます。

[19069] 14 May 16:30:51.170 # +sdown master mymaster db0 6379
[19069] 14 May 16:30:52.386 # +odown master mymaster db0 6379 #quorum 2/2
[19069] 14 May 16:30:52.386 # +failover-triggered master mymaster db0 6379
[19069] 14 May 16:30:52.386 # +failover-state-wait-start master mymaster db0 6379 #starting in 13910 milliseconds
[19069] 14 May 16:31:06.379 # +failover-state-select-slave master mymaster db0 6379
[19069] 14 May 16:31:06.480 # +selected-slave slave db1:6379 db1 6379 @ mymaster db0 6379
[19069] 14 May 16:31:06.480 * +failover-state-send-slaveof-noone slave db1:6379 db1 6379 @ mymaster db0 6379
[19069] 14 May 16:31:06.583 * +failover-state-wait-promotion slave db1:6379 db1 6379 @ mymaster db0 6379
[19069] 14 May 16:31:06.901 # +promoted-slave slave db1:6379 db1 6379 @ mymaster db0 6379
[19069] 14 May 16:31:06.902 # +failover-state-reconf-slaves master mymaster db0 6379
[19069] 14 May 16:31:06.991 * +slave-reconf-sent slave db0:6380 db0 6380 @ mymaster db0 6379
[19069] 14 May 16:31:07.294 * +slave-reconf-inprog slave db0:6380 db0 6380 @ mymaster db0 6379
[19069] 14 May 16:31:08.316 * +slave-reconf-done slave db0:6380 db0 6380 @ mymaster db0 6379
[19069] 14 May 16:31:08.417 # +failover-end master mymaster db0 6379
[19069] 14 May 16:31:08.417 # +switch-master mymaster db0 6379 db1 6379
[19069] 14 May 16:31:08.548 * +slave slave db0:6380 db0 6380 @ mymaster db1 6379
[19069] 14 May 16:31:09.068 * +sentinel sentinel db0:26380 db0 26380 @ mymaster db1 6379
[19069] 14 May 16:31:12.258 * +sentinel sentinel db1:26379 db1 26379 @ mymaster db1 6379

SentinelがMasterのダウンを検知すると状態がSDOWNに、quorumパラメータで指定した数のSDOWNが揃うと次はODOWNへと遷移、その後フェイルオーバー処理が開始されます。

最后确保新的主节点和从节点正常运行。

redis db1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:db0,6380,online

我已经尝试过了以上和 Sentinel 的故障转移功能的操作确认。

哨兵 API

由于Sentinel提供了一些API,所以我想简单介绍一下。

## SENTINEL masters
# 監視対象のMasterに関する情報を確認
redis 127.0.0.1:26379> sentinel masters
1)  1) "name"
    2) "mymaster"
    3) "ip"
    4) "127.0.0.1"
    5) "port"
    6) "6379"
    7) "runid"
    8) "b3b31e6c6d1fbb0cec5d179fd666ce00ea103746"
    9) "flags"
   10) "master"
   11) "pending-commands"
   12) "0"
   13) "last-ok-ping-reply"
   14) "568"
   15) "last-ping-reply"
   16) "568"
   17) "info-refresh"
   18) "9745"
   19) "num-slaves"
   20) "1"
   21) "num-other-sentinels"
   22) "1"
   23) "quorum"
   24) "2"

## SENTINEL slaves <master name>
# Slaveに関する情報を確認
redis 127.0.0.1:26379> sentinel slaves mymaster
1)  1) "name"
    2) "127.0.0.1:6380"
    3) "ip"
    4) "127.0.0.1"
    5) "port"
    6) "6380"
    7) "runid"
    8) "17c0f7e7e4d2af0f5f6140ea0ceb0d82d0010aed"
    9) "flags"
   10) "s_down,slave,disconnected"
   11) "pending-commands"
   12) "0"
   13) "last-ok-ping-reply"
   14) "709377"
   15) "last-ping-reply"
   16) "709377"
   17) "s-down-time"
   18) "704333"
   19) "info-refresh"
   20) "712808"
   21) "master-link-down-time"
   22) "0"
   23) "master-link-status"
   24) "ok"
   25) "master-host"
   26) "127.0.0.1"
   27) "master-port"
   28) "6379"
   29) "slave-priority"
   30) "100"

## SENTINEL is-master-down-by-addr <ip> <port>
# Masterの死活確認
redis 127.0.0.1:26379> sentinel is-master-down-by-addr 127.0.0.1 6379
1) (integer) 0  ## 0:UP, 1:DOWN
2) "397dec99760d5d30043941fe4c1c35ba99e99ebf"  ## Sentinel(subjective leader)のrun_id

## SENTINEL get-master-addr-by-name <master name>
# MasterのIP, Portを確認
redis 127.0.0.1:26379> sentinel get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6379"

## SENTINEL reset
# Sentinelの現在の状態をリセット(フェイルオーバー処理中であっても)
redis 127.0.0.1:26379> sentinel reset mymaster
(integer) 1

我认为在创建与 Sentinel 相关的管理工具时,使用支持 Sentinel API 的客户端库会更加方便。

以下是关于故障转移处理行为的部分内容。

升職奴隶的选择

当然,我们要找的是作为从服务器正常运行的进程。简单来说,我们希望从服务器与主服务器连接稳定(没有宕机时间),并且在最近的5000毫秒内能够对Sentinel的PING/INFO命令做出响应(详细信息请参考官方文档和src/sentinel.c)。

如果有多个可选择的受控节点,则选择slave_priority值较小的Slave。

redis db0:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_priority:100  ## <- この値
slave_read_only:1
connected_slaves:0

如果存在具有相同slave_priority的从节点,将选择run_id较小的从节点。

redis db0:6380> info
# Server
redis_version:2.6.10
redis_git_sha1:00000000
redis_git_dirty:0
redis_mode:standalone
os:Linux 2.6.18-194.26.1.el5 x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.1.2
process_id:17468
run_id:17c0f7e7e4d2af0f5f6140ea0ceb0d82d0010aed  ## <- この値
tcp_port:6380
uptime_in_seconds:1738
uptime_in_days:0
lru_clock:538965

截止到2013年6月,目前并没有公开可用于更改slave_priority的API,因此只是简单地选择run_id较小的slave。选择slave的算法将来可能会有变化。

Sentinels/Slaves的自动检测

不需要在Sentinel的配置中包含Slave列表的原因是因为Sentinel通过Pub/Sub进行信息共享。即使在途中在线添加了另一个Sentinel或Slave,该信息也会传递给其他Sentinel。

## Sentinelは "__sentinel__:hello" チャンネルを利用している
redis db0:6379> subscribe __sentinel__:hello
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__sentinel__:hello"
3) (integer) 1
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1:26380:77887a367e1c76ee9dc15f67a2fb3dc49bb00bf4:1"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1:26379:3a92da7269b69fa1dcce5915068c4af6e8caf161:1"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1:26380:77887a367e1c76ee9dc15f67a2fb3dc49bb00bf4:1"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1:26379:3a92da7269b69fa1dcce5915068c4af6e8caf161:1"

消息的内容是 host:port:run_id:can-failover,每5秒发布到 __sentinel__:hello 频道,所有的 Sentinel 都订阅此频道以进行信息共享。

复制的注意事项

Redis的复制与MySQL等关系型数据库管理系统的复制有很多不同之处。在Redis开始复制时,它会将所有数据写入磁盘,然后再传输到从服务器,因此需要注意I/O和网络带宽。不过,据说Redis v2.8已经实现了PSYNC(部分重新同步),因此这个问题似乎已经得到解决。

我希望能够继续进行Sentinel的验证工作。

bannerAds