标签:redis集群 sentinel leader选举 缓存集群 cluster
在前两篇Redis中sentinel集群的搭建和Jedis测试 图文教程[一] 和Redis中sentinel集群的搭建和Jedis测试 图文教程[二] 中分别简述了Redis中sentinel集群的搭建和Java代码的Jedis测试。
这篇主要来简单分析一下Redis-sentinel集群的原理,根据追踪sentinel信息来完成Redis-sentinel集群测试中的详细的原理分析。包括master-slave各个中的sentinel信息的分析,failover过程,master宕机后的leader选举过程等等方面深层次详细简述了其各个原理。
HA(High Available,高可用性群集)机集群系统简称,是保证业务连续性的有效解决方案,一般有两个或两个以上的节点,且分为活动节点及备用节点。通常把正在执
行业务的称为活动节点,而作为活动节点的一个备份的则称为备用节点。当活动节点出现问题,导致正在运行的业务(任务)不能正常运行时,备用节点此时就会侦测到,并立即接续活动节点来执行业务。从而实现业务的不中断或短暂中断。From 百度百科.
Redis 一般以主/从方式部署(这里讨论的应用从实例主要用于备份,主实例提供读写)该方式要实现 HA 主要有如下几种方案:
1)keepalived:通过 keepalived 的虚拟 IP,提供主从的统一访问,在主出现问题时, 通过 keepalived 运行脚本将从提升为主,待主恢复后先同步后自动变为主,该方案的好处是主从切换后,应用程序不需要知道(因为访问的虚拟 IP 不变),坏处是引入 keepalived 增加部署复杂性,在有些情况下会导致数据丢失;
2) zookeeper: 通过 zookeeper 来监控主从实例, 维护最新有效的 IP, 应用通过 zookeeper取得 IP,对 Redis 进行访问,该方案需要编写大量的监控代码;
3)sentinel:通过 Sentinel 监控主从实例,自动进行故障恢复,该方案有个缺陷:因为主从实例地址(IP&PORT)是不同的, 当故障发生进行主从切换后, 应用程序无法知道新地址,故 在 Jedis2.2.2 中 新 增 了 对 Sentinel 的 支 持 , 应 用 通 过redis.clients.jedis.JedisSentinelPool.getResource()取得的Jedis实例会及时更新到新的主实例地址。
下面是该方案的部署逻辑图。
详情请见Redis中sentinel集群的搭建和Jedis测试 图文教程[一]
由于 sentinel 服务器已经在 redis 服务器的环境中(redis-sentinel),我们这里就直接使用它们(在生产环境中,sentinel 服务器和 redis-server 服务器一般是分离的,部署在不同的pc-server 上面,同时 sentinel 的个数和 redis-server 个数也没联系,下面为了方便学习使用将3 台 sentinel 服务都放到了一台 pc 上)。
注意: sentinel 配置文件只和默认的 master 有关系,和 slave 都没有关系。我们上面的例子是用了 3 个 redis-server 和 3 个 redis-sentinel,其实 redis-sentinel的个数不一定要和 redis-sever 对应,1~n 个都可以。
首先要清楚,sentinel是一个独立于redis之外的进程,不对外提供key/value服务。在redis的安装目录下名称叫 redis-sentinel 。 主要用来监控redis-server进程,进行master/slave管理,如果你的redis没有运行在master/slave模式下,不需要设置sentinel。
分别启动 redis-server 和redis-sentinel。
1)启动 redis-0 时 redis-0 的 sentinel 控制台
2)启动 redis-1 时 reids-1 的 sentinel 控制台
启动 redis-1 时 reids-0 的 sentinel 控制台
3)启动 redis-2 时 reids-2 的 sentinel 控制台
启动 redis-2 时 reids-0 的 sentinel 控制台
启动 redis-2 时 reids-1 的 sentinel 控制台
通过上的控制输出信息可以看出,在依次启动服务时,对用控制台输出了+sentinel、+slave、-sdown 等信息,说明各个 sentinel 之间进行了通讯,而且也监控到了 redis-server 的情况。+sentinel 表示有新的 sentinel 实例加入到监控。提示:首次构建 sentinel 环境时,必须首先启动 master 机器。
4)查看相关信息
使用 # netstat -ntlp | grep redis 命令可以看到当前 redis 运行情况。
通过 redis-cli 查看 redis-server 的状态
/usr/local/webserver/redis/redis-cli -h 127.0.0.1 -p 6379 -a abcd123457 info Replication
(上面的 -a 用来输入密码)
说明:info 指令
该指令将会打印完整的服务信息,包括集群,我们只需要关注”Replication”部分(在上面的命令中,我们在 info 后面加上了 Replication 的限制,如果不加,这还会输出 Server、Clients、Memory、Persistence、Stats、CPU 和 Keyspace 等信息),这部分信息将会告诉我们”当前 server 的角色”以及指向它的所有的 slave 信息。可以通过在任何一个 slave 上,使用”INFO”指令获得当前 slave 所指向的 master 信息。下面是 slave1 的 Replication 信息。
同时,该指令不仅可以帮助我们获得集群的情况,当然 sentinel 组件也是使用”INFO”做同样的事情。下面是 slave2 的 sentinel 信息。
通过上面信息,可以清楚看到 redis 服务状态和主从关系。
5)failover 测试
当上述部署环境稳定后,我们直接关闭 redis-0,在等待”down-after-milliseconds”秒之后(30 秒),redis-0/redis-1/redis-2 的 sentinel 窗口会立即打印”+sdown”、”+odown”、”+failover”、”+selected-slave”、 “+promoted-slave”、 “+slave-reconf”等等一系列指令, 这些指令标明当 master失效后,sentinel 组件进行 failover 的过程。
模拟 mater 宕机的情况。此时各 sentinel 控制台输出如下信息。
redis-0 上的 sentinel 信息.
redis-1 上的 sentinel 信息
redis-2 上的 sentinel 信息
从上面三个窗口的信息可以看出, 当 master 宕机后, 三个 sentinel(哨兵)进行了对 master进行了故障转移。
{从 redis-1 的 sentinel 控制台可以看出,进行了下面的操作。
a.+sdown mater mymaster 127.0.0.1 6379 (主观认为 mater 失效);
b.+odown mater mymaster 127.0.0.1 6379 #quorum 2/2(已经有两个哨兵认为 master 主观失效,则认为 mater 客观失效);
c.+new-epoch 1(准备进行新 mater 的选取);
d.+try-failover master mymaster 127.0.0.1 6379(尝试热备份切换,master 让出位置);
e.+vote-for-leader 1eb0f03b7a7815c3c5506b0fa041ad8d6ca9db90 1(投票选举 Leader);
f.127.0.0.1:16379 voted for 1eb0f03b7a7815c3c5506b0fa041ad8d6ca9db90 1(投票选举Leader);
g.127.0.0.1:36379 voted for 1eb0f03b7a7815c3c5506b0fa041ad8d6ca9db90 1(投票选举Leader);
h.+elected-leader master mymaster 127.0.0.1 6379(之前被选举出来的 master);
i.+failover-state-select-slave master mymaster 127.0.0.1 6379(Leader 开始查找合适的slave);
j.+selected-slave slave 127.0.0.1:63792 127.0.0.1 63792 @ mymaster 127.0.0.1 6379 (leader已经找到合适的 slave);
k.+failover-state-send-slaveof-noone slave 127.0.0.1:63792 127.0.0.1 63792 @ mymaster 127.0.0.1 6379(Leader 向 slave 发送“slaveof no one”指令,此时 slave 已经完成角色转换,此 slave 即为 master);
l.+failover-state-wait-promotion slave 127.0.0.1:63792 127.0.0.1 63792 @ mymaster 127.0.0.1 6379(等待其他 sentinel 确认 slave);
m.+promoted-slave slave 127.0.0.1:63792 127.0.0.1 63792 @ mymaster 127.0.0.1 6379(确认成功);
n.+failover-state-reconf-slaves master mymaster 127.0.0.1 6379 (开始对slaves进行reconfig 操作);
o.+slave-reconf-sent slave 127.0.0.1:63791 127.0.0.1 63791 @ mymaster 127.0.0.1 6379 (向指定的 slave 发送“slaveof”指令,告知此 slave 跟随新的 master);
p. +slave-reconf-inprog slave 127.0.0.1:63791 127.0.0.1 63791 @ mymaster 127.0.0.1 6379(此 slave 正在执行 slaveof + SYNC 过程,如过 slave 收到“+slave-reconf-sent”之后将会执行 slaveof 操作,循环 n);
q.+slave-reconf-done slave 127.0.0.1:63791 127.0.0.1 63791 @ mymaster 127.0.0.1 6379(此 slave 同步完成,此后 leader 可以继续下一个 slave 的 reconfig 操作);
r.+failover-end master mymaster 127.0.0.1 6379(故障转移结束);
s.+switch-master mymaster 127.0.0.1 6379 127.0.0.1 63792(故障转移成功后,各个sentinel 实例开始监控新的 master);
t.+slave slave 127.0.0.1:63791 127.0.0.1 63791 @ mymaster 127.0.0.1 63792(下面几步在给新的 master 加入 slave);
u.+slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 63792;
v.+sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 63792。
当环境稳定后,我们发现,redis-2 被提升(“promoted”)为 master,且 redis-1 也通过”slave-reconf”过程之后跟随了 redis-2。
如果此时 redis-0 服务器恢复正常, sentinel 会自动将 redis-0 作为 slave 加入到 redis-2 中。
下面是 redis-0 的 sentinel 控制台输出的信息。
再次查看 redis-2(当前 master 的 info)
提示:sentinel 实例需要全程处于启动状态,如果只启动 server 而不启动相应的 sentinel,仍然不能确保 server 能够正确的被监控和管理。
1)SDOWN 和 ODOWN 转换过程
【名词解释】
SDOWN:subjectively down,直接翻译的为”主观”失效,即当前 sentinel 实例认为某个redis 服务为”不可用”状态。
ODOWN:objectively down,直接翻译为”客观”失效,即多个 sentinel 实例都认为 master处于”SDOWN”状态,那么此时 master 将处于 ODOWN,ODOWN 可以简单理解为 master已经被集群确定为”不可用”,将会开启 failover。
( SDOWN 适合于 master 和 slave,但是 ODOWN 只会使用于 master;当 slave 失效超过”down-after-milliseconds”后,那么所有 sentinel 实例都会将其标记为”SDOWN”。)
【转换过程】
a.每个 sentinel 实例在启动后,都会和已知的 slaves/master 以及其他 sentinels 建立 TCP连接,并周期性发送 PING(默认为 1 秒);
b.在交互中,如果 redis-server 无法在”down-after-milliseconds”时间内响应或者响应错误信息,都会被认为此 redis-server 处于 SDOWN 状态;
c.如果 b.中 SDOWN 的 server 为 master, 那么此时 sentinel 实例将会向其他 sentinel 间歇性(一秒)发送”is-master-down-by-addr “指令并获取响应信息, 如果足够多的 sentinel 实例检测到 master 处于 SDOWN,那么此时当前 sentinel 实例标记 master 为 ODOWN…其他 sentinel实例做同样的交互操作.配置项”sentinel monitor “,如果检测到 master 处于 SDOWN 状态的slave 个数达到,那么此时此 sentinel 实例将会认为 master 处于 ODOWN;
d.每个 sentinel 实例将会间歇性(10 秒)向 master 和 slaves 发送”INFO”指令,如果 master失效且没有新 master 选出时,每 1 秒发送一次”INFO”;”INFO”的主要目的就是获取并确认当前集群环境中 slaves 和 master 的存活情况;
经过上述过程后,所有的 sentinel 对 master 失效达成一致后,开始 failover。
2) Sentinel 与 slaves”自动发现”机制
在 sentinel 的配置文件中(local-sentinel.conf),都指定了 port,此 port 就是 sentinel 实例侦听其他 sentinel 实例建立链接的端口.在集群稳定后,最终会每个 sentinel 实例之间都会建立一个 tcp 链接,此链接中发送”PING”以及类似于”is-master-down-by-addr”指令集,可用用来检测其他 sentinel 实例的有效性以及”ODOWN”和”failover”过程中信息的交互。
在 sentinel 之间建立连接之前,sentinel 将会尽力和配置文件中指定的 master 建立连接。sentinel 与 master 的连接中的通信主要是基于 pub/sub 来发布和接收信息,发布的信息内容包括当前 sentinel 实例的侦听端口。
3)Leader 选举
其实在 sentinels 故障转移中,仍然需要一个“Leader”来调度整个过程:master 的选举以及 slave 的重配置和同步。当集群中有多个 sentinel 实例时,如何选举其中一个 sentinel 为leader 呢?
redis2.8.7的选举有两个条件,首先是要下面的条件过滤掉一些节点
我们期望有足够多的sentinel实例, 这样能够确保当leader失效时, 能够选举某个sentinel为 leader,以便进行 failover。如果 leader 无法产生,比如较少的 sentinels 实例有效,那么failover 过程将无法继续。
4)failover 过程
在 Leader 触发 failover 之前,首先 wait 数秒(随即 0~5),以便让其他 sentinel 实例准备和调整,如果一切正常,那么 leader 就需要开始将一个 salve 提升为 master,此 slave 必须为状态良好(不能处于 SDOWN/ODOWN 状态)且权重值最低(redis.conf 中)的, 当 master 身份被确认后,开始 failover。
1)redis 的水平扩展。 前文所实现的是 redis 的主从 HA 集群 (从服务器做备份而存在) ,试想当缓存到了一个级别一台服务器已经不能满足了,就想到了 redis 的分布式,将缓存放到分配到多台服务器中。Redis 官方也提供了 redis cluster 来实现分布式,但目还没有正式版发布(redis 3.0貌似提供了支持,还没来得及研究)。Java 可以通过 jedis 的 ShardedJedis 来做分片 。
2)redis 的监控。一个东西运行的是否正常、稳定和性能情况,这就涉及到了对它的监控。目前 redis 的监控工具有:redmon、redis-live 等。本文暂不做监控,读者可参考其他资料学习使用。
3)集群时的读写分离。主用来写,从用来读。在 redis 的 HA 集群中,主从服务器是变化的,这就导致在程序中,不容易获得当前哪台服务是主,哪几台服务是从。我们可以自己通过代码实现获得从服务器的 jedis 实例,具体可以参见Redis中sentinel集群的搭建和Jedis测试 图文教程[二] 从而达到读写分离。
4)“缓存数据同步”也是所有缓存工具的一个必须思考的问题。
Redis中sentinel集群的搭建和Jedis测试 图文教程[三]
标签:redis集群 sentinel leader选举 缓存集群 cluster
原文地址:http://blog.csdn.net/wtyvhreal/article/details/46574203