Redis哨兵机制(sentinel)

一、简介:

一、是什么:

    Redis-Sentinel是Redis官方推荐的高可用(HA)方案,当用Reids 作master-slave高可用方案时,假如master宕机了,redis自己(包括它的不少客服端)都没有实现自动的主备切换,而Redis-Sentinel自己也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能自动切换。html

二、功能

  • 不时监控redis是否按照预期的良好的运行。
  • 若是发现某个redis节点运行出现情况,可以通知别外一个进程(如它的客户端)。
  • 可以进行自动切换。当一个master节点不可用时,可以选举出master的多个slave(若是超过一个slave的话)中的一个来做为新的master,其它的slave节点会将他的master地址改成新提高为master的服务器的地址。

四、优缺点:

优势:

  • 哨兵模式是基于主从模式的,全部主从的优势,哨兵模式都有。
  • 主从能够自动切换,系统更健壮,可用性更高

缺点:

  • redis较难支持在线扩容,在集群容量达上限时在线扩容变的很复杂。

二、原理:

一、哨兵的工做方式:

  1. 每一个Sentinel(哨兵)进程以每秒钟一次的频率向整个redis集群中的master主服务器、slave从服务器以及其余的Sentinel(哨兵)进程发送一个ping命令。
  2. 若是一个实例距离最后一次有效回复ping命令的时间超过down-after-milliseconds选项所指定的值则这个实例会被Sentinel标记为主观下线(SDOWN)。
  3. 如是是master主服务器被标记为SDOWN,则正在监控这个服务器的全部Sentinel都要以每秒一次的频率确认服务器是否真的已经进入SDOWN(主观下线状态)。
  4. 当有足够数量(≥配置文件配置值)的Sentinel在指定的时间内确认了master进入了SDOWN状态,则master被标记为ODOWN(客观下线状态)。
  5. 在通常状况下,每一个Sentinel会每10秒向redis 主服务器和从服务器发送Info命令。可是当master被标记为客观下线时,频率改成1秒一次。
  6. 若没有足够数量的Sentinel赞成master服务器下线,则master的SDOWN状态被移除,若master从新向Sentinel发送ping命令返回了有效回复,则master的SDOWN状态被移除。

二、原理

  1. Sentinel集群经过给定的配置文件发现master,启动时会监控master。经过向master发送info信息得到该服务下面的全部从服务器。
  2. Sentinel集群经过命令链接向被监控的主从服务器发送hello信息(每秒一次),该信息包括Sentinel自己的ip、端口、id等内容,以此来向其余Sentinel宣告本身的存在。
  3. Sentinel集群经过订阅链接接收其余Sentinel发送的hello信息,以此来发现监视同一个主服务器的其余Sentinel;集群之间会互相建立命令链接用于通讯,由于已经有主从服务器做为发送和接收hello信息的中介,Sentinel之间不会建立订阅链接。
  4. Sentinel集群使用Sentinel命令来检测实例的状态,若是指定的时间内(down-after-milliseconds)没有回复或者返回错误回复,那么该实例被判为主观下线SDOWN。
  5. 当failover主备切换被触发后,failover并不会立刻进行,还须要Sentinel集群中另外quorum个其余Sentinel受权,成功后进入ODOWN客观下线状态,以后再进行failover。
  6. Sentinel向选为master的slave发送slaveof no one 命令,选择slave的条件是首先会根据slave的优先级来排序,优先级越小排名越靠前。若是相同,则查看复制的下标,哪一个接收master的复制数据越多哪一个越靠前,若是两个都同样就选择进程ID较小的。
  7. Sentinel被受权后会得到宕机的master的一份最新配置版本号(config-epoch)当failover结束后,这个版本号将会用于最新的配置,经过广播的形式通知其余Sentinel,其它的Sentinel则更新对应的master配置。

1-3是自动发现机制

  • 以10秒一次的频率,向被监控的master发送Info命令,根据回复获取当前master信息。
  • 以1秒一次的频率,向全部的redis服务器包括 Sentinel 发送ping命令,经过回复判断服务器是否在线
  • 以2秒一次的频率,经过  向全部被监控的master,slave服务器发送的当前Sentinel,master信息的消息。

四、是检测机制,五、6是failover机制,7是更新配置机制。

注意:

  • 由于redis采用的是异步复制,没有办法避免数据的丢失。但能够经过如下配置来使得数据不会丢失:min-slaves-to-write 1  ; min-slaves-max-lag 10。
  • 一个redis不管是master仍是slave,都必须在配置中指定一个slave优先级。
  • 要注意到master也是有可能经过failover变成slave的。
  • 若是一个redis的slave优先级配置为0,那么它将永远不会被选为master,可是它依然会从master哪里复制数据。

三、SDOWN和ODOWN

  1. sentinel对于不可用有两种不一样的见解,一个叫主观不可用(SDOWN),另一个叫客观不可用(ODOWN)。
  2. SDOWN是sentinel本身主观上检测到的关于master的状态,ODOWN须要必定数量的sentinel达成一致意见才能认为一个master客观上已经宕掉,各个sentinel之间经过命令SENTINEL is_master_down_by_addr来得到其它sentinel对master的检测结果。
  3. 从sentinel的角度来看,若是发送了PING心跳后,在必定时间内没有收到合法的回复,就达到了SDOWN的条件。这个时间在配置中经过is-master-down-after-milliseconds参数配置。
  4. 从SDOWN切换到ODOWN不须要任何一致性算法,只须要一个gossip协议:若是一个sentinel收到了足够多的sentinel发来消息告诉它某个master已经down掉了,SDOWN状态就会变成ODOWN状态。若是以后master可用了,这个状态就会相应地被清理掉。
  5. 真正进行failover须要一个受权的过程,可是全部的failover都开始于一个ODOWN状态。
  6. ODOWN状态只适用于master,对于不是master的redis节点sentinel之间不须要任何协商,slaves和sentinel不会有ODOWN状态。

四、配置版本号

  1. 为何要先得到大多数sentinel的承认时才能真正去执行failover呢?
  2. 当一个sentinel被受权后,它将会得到宕掉的master的一份最新配置版本号,当failover执行结束之后,这个版本号将会被用于最新的配置。由于大多数sentinel都已经知道该版本号已经被要执行failover的sentinel拿走了,因此其余的sentinel都不能再去使用这个版本号。这意味着,每次failover都会附带有一个独一无二的版本号。咱们将会看到这样作的重要性。
  3. 并且,sentinel集群都遵照一个规则:若是sentinel A推荐sentinel B去执行failover,B会等待一段时间后,自行再次去对同一个master执行failover,这个等待的时间是经过failover-timeout配置项去配置的。从这个规则能够看出,sentinel集群中的sentinel不会再同一时刻并发去failover同一个master,第一个进行failover的sentinel若是失败了,另一个将会在必定时间内进行从新进行failover,以此类推。
  4. redis sentinel保证了活跃性:若是大多数sentinel可以互相通讯,最终将会有一个被受权去进行failover.
    redis sentinel也保证了安全性:每一个试图去failover同一个master的sentinel都会获得一个独一无二的版本号。

五、配置传播

  1. 一旦一个sentinel成功地对一个master进行了failover,它将会把关于master的最新配置经过广播形式通知其它sentinel,其它的sentinel则更新对应master的配置。
  2. 一个faiover要想被成功实行,sentinel必须可以向选为master的slave发送SLAVEOF NO ONE命令,而后可以经过INFO命令看到新master的配置信息。
  3. 当将一个slave选举为master并发送SLAVEOF NO ONE后,即便其它的slave还没针对新master从新配置本身,failover也被认为是成功了的,而后全部sentinels将会发布新的配置信息。

新配在集群中相互传播的方式,就是为何咱们须要当一个sentinel进行failover时必须被受权一个版本号的缘由。node

  1. 每一个sentinel使用##发布/订阅##的方式持续地传播master的配置版本信息,配置传播的##发布/订阅##管道是:__sentinel__:hello
  2. 由于每个配置都有一个版本号,因此以版本号最大的那个为标准。

举个栗子:

  1. 假设有一个名为mymaster的地址为192.168.1.50:6379。一开始,集群中全部的sentinel都知道这个地址,因而为mymaster的配置打上版本号1。
  2. 一段时候后mymaster死了,有一个sentinel被受权用版本号2对其进行failover。
  3. 若是failover成功了,假设地址改成了192.168.1.50:9000,此时配置的版本号为2,进行failover的sentinel会将新配置广播给其余的sentinel
  4. 因为其余sentinel维护的版本号为1,发现新配置的版本号为2时,版本号变大了,说明配置更新了,因而就会采用最新的版本号为2的配置。

这意味着sentinel集群保证了第二种活跃性:一个可以互相通讯的sentinel集群最终会采用版本号最高且相同的配置。redis

六、Sentinel之间和Slaves之间的自动发现机制

  1. 虽然sentinel集群中各个sentinel都互相链接彼此来检查对方的可用性以及互相发送消息。可是你不用在任何一个sentinel配置任何其它的sentinel的节点。由于sentinel利用了master的发布/订阅机制去自动发现其它也监控了统一master的sentinel节点。经过向名为__sentinel__:hello的管道中发送消息来实现。
  2. 一样,你也不须要在sentinel中配置某个master的全部slave的地址,sentinel会经过询问master来获得这些slave的地址的。
  3. 每一个sentinel经过向每一个master和slave的发布/订阅频道__sentinel__:hello每秒发送一次消息,来宣布它的存在。
  4. 每一个sentinel也订阅了每一个master和slave的频道__sentinel__:hello的内容,来发现未知的sentinel,当检测到了新的sentinel,则将其加入到自身维护的master监控列表中。
  5. 每一个sentinel发送的消息中也包含了其当前维护的最新的master配置。若是某个sentinel发现本身的配置版本低于接收到的配置版本,则会用新的配置更新本身的master配置。
  6. 在为一个master添加一个新的sentinel前,sentinel老是检查是否已经有sentinel与新的sentinel的进程号或者是地址是同样的。若是是那样,这个sentinel将会被删除,而把新的sentinel添加上去。

七、网络隔离时的一致性

例子:算法

  1. 有三个主机,每一个主机分别运行一个redis和一个sentinel。初始状态下redis3是master, redis1和redis2是slave。
  2. 以后redis3所在的主机网络不可用了,sentinel1和sentinel2启动了failover并把redis1选举为master。
  3. Sentinel集群的特性保证了sentinel1和sentinel2获得了关于master的最新配置。可是sentinel3依然是旧的配置,由于它与外界隔离了。

当网络恢复之后,咱们知道sentinel3将会更新它的配置。可是,若是客户端所链接的master被网络隔离,会发生什么呢?安全

  1. 客户端将依然能够向redis3写数据,可是当网络恢复后,redis3就会变成redis的一个slave,那么,在网络隔离期间,客户端向redis3写的数据将会丢失。
  2. 由于redis采用的是异步复制,在这样的场景下,没有办法避免数据的丢失。然而,你能够经过如下配置来配置redis3和redis1,使得数据不会丢失。
min-slaves-to-write 1
min-slaves-max-lag 10
  • 经过上面的配置,当一个redis是master时,若是它不能向至少一个slave写数据(上面的min-slaves-to-write指定了slave的数量),它将会拒绝接受客户端的写请求。
  • 因为复制是异步的,master没法向slave写数据意味着slave要么断开链接了,要么不在指定时间内向master发送同步数据的请求了(上面的min-slaves-max-lag指定了这个时间)。

八、Slave选举与优先级

当一个sentinel准备好了要进行failover,而且收到了其余sentinel的受权,那么就须要选举出一个合适的slave来作为新的master。服务器

slave的选举主要会评估slave的如下几个方面:网络

  • 与master断开链接的次数并发

  • Slave的优先级less

  • 数据复制的下标(用来评估slave当前拥有多少master的数据)异步

  • 进程ID

若是一个slave与master失去联系超过10次,而且每次都超过了配置的最大失联时间(down-after-milliseconds),若是sentinel在进行failover时发现slave失联,那么这个slave就会被sentinel认为不适合用来作新master的。

更严格的定义是,若是一个slave持续断开链接的时间超过

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

就会被认为失去选举资格。
符合上述条件的slave才会被列入master候选人列表,并根据如下顺序来进行排序:

  1. sentinel首先会根据slaves的优先级来进行排序,优先级越小排名越靠前。

  2. 若是优先级相同,则查看复制的下标,哪一个从master接收的复制数据多,哪一个就靠前。

  3. 若是优先级和下标都相同,就选择进程ID较小的那个。

一个redis不管是master仍是slave,都必须在配置中指定一个slave优先级。要注意到master也是有可能经过failover变成slave的。

若是一个redis的slave优先级配置为0,那么它将永远不会被选为master。可是它依然会从master哪里复制数据。

三、配置

一、redis.conf 配置

################################# REPLICATION #################################
#复制选项,slave复制对应的master。
# slaveof <masterip> <masterport>

#若是master设置了requirepass,那么slave要连上master,须要有master的密码才行。masterauth就是用来配置master的密码,这样能够在连上master后进行认证。
# masterauth <master-password>

#当从库同主机失去链接或者复制正在进行,从机库有两种运行方式:1) 若是slave-serve-stale-data设置为yes(默认设置),从库会继续响应客户端的请求。2) 若是slave-serve-stale-data设置为no,除去INFO和SLAVOF命令以外的任何请求都会返回一个错误”SYNC with master in progress”。
slave-serve-stale-data yes

#做为从服务器,默认状况下是只读的(yes),能够修改为NO,用于写(不建议)。
slave-read-only yes

#是否使用socket方式复制数据。目前redis复制提供两种方式,disk和socket。若是新的slave连上来或者重连的slave没法部分同步,就会执行全量同步,master会生成rdb文件。有2种方式:disk方式是master建立一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave。socket是master建立一个新的进程,直接把rdb文件以socket的方式发给slave。disk方式的时候,当一个rdb保存的过程当中,多个slave都能共享这个rdb文件。socket的方式就的一个个slave顺序复制。在磁盘速度缓慢,网速快的状况下推荐用socket方式。
repl-diskless-sync no

#diskless复制的延迟时间,防止设置为0。一旦复制开始,节点不会再接收新slave的复制请求直到下一个rdb传输。因此最好等待一段时间,等更多的slave连上来。
repl-diskless-sync-delay 5

#slave根据指定的时间间隔向服务器发送ping请求。时间间隔能够经过 repl_ping_slave_period 来设置,默认10秒。
# repl-ping-slave-period 10

#复制链接超时时间。master和slave都有超时时间的设置。master检测到slave上次发送的时间超过repl-timeout,即认为slave离线,清除该slave信息。slave检测到上次和master交互的时间超过repl-timeout,则认为master离线。须要注意的是repl-timeout须要设置一个比repl-ping-slave-period更大的值,否则会常常检测到超时。
# repl-timeout 60

#是否禁止复制tcp连接的tcp nodelay参数,可传递yes或者no。默认是no,即便用tcp nodelay。若是master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减小包的数量和更小的网络带宽。可是这也可能带来数据的延迟。默认咱们推荐更小的延迟,可是在数据量传输很大的场景下,建议选择yes。
repl-disable-tcp-nodelay no

#复制缓冲区大小,这是一个环形复制缓冲区,用来保存最新复制的命令。这样在slave离线的时候,不须要彻底复制master的数据,若是能够执行部分同步,只须要把缓冲区的部分数据复制给slave,就能恢复正常复制状态。缓冲区的大小越大,slave离线的时间能够更长,复制缓冲区只有在有slave链接的时候才分配内存。没有slave的一段时间,内存会被释放出来,默认1m。
# repl-backlog-size 5mb

#master没有slave一段时间会释放复制缓冲区的内存,repl-backlog-ttl用来设置该时间长度。单位为秒。
# repl-backlog-ttl 3600

#当master不可用,Sentinel会根据slave的优先级选举一个master。最低的优先级的slave,当选master。而配置成0,永远不会被选举。
slave-priority 100

#redis提供了可让master中止写入的方式,若是配置了min-slaves-to-write,健康的slave的个数小于N,mater就禁止写入。master最少得有多少个健康的slave存活才能执行写命令。这个配置虽然不能保证N个slave都必定能接收到master的写操做,可是能避免没有足够健康的slave的时候,master不能写入来避免数据丢失。设置为0是关闭该功能。
# min-slaves-to-write 3

#延迟小于min-slaves-max-lag秒的slave才认为是健康的slave。
# min-slaves-max-lag 10

二、sentinel.conf配置

port 20086      #默认端口26379

dir "/tmp"

logfile "/var/log/redis/sentinel_20086.log"

daemonize yes

#格式:sentinel <option_name> <master_name> <option_value>;#该行的意思是:监控的master的名字叫作T1(自定义),地址为127.0.0.1:10086,行尾最后的一个2表明在sentinel集群中,多少个sentinel认为masters死了,才能真正认为该master不可用了。
sentinel monitor T1 127.0.0.1 10086 2

#sentinel会向master发送心跳PING来确认master是否存活,若是master在“必定时间范围”内不回应PONG 或者是回复了一个错误消息,那么这个sentinel会主观地(单方面地)认为这个master已经不可用了(subjectively down, 也简称为SDOWN)。而这个down-after-milliseconds就是用来指定这个“必定时间范围”的,单位是毫秒,默认30秒。
sentinel down-after-milliseconds T1 15000

#failover过时时间,当failover开始后,在此时间内仍然没有触发任何failover操做,当前sentinel将会认为这次failoer失败。默认180秒,即3分钟。
sentinel failover-timeout T1 120000

#在发生failover主备切换时,这个选项指定了最多能够有多少个slave同时对新的master进行同步,这个数字越小,完成failover所需的时间就越长,可是若是这个数字越大,就意味着越多的slave由于replication而不可用。能够经过将这个值设为 1 来保证每次只有一个slave处于不能处理命令请求的状态。
sentinel parallel-syncs T1 1

#sentinel 链接设置了密码的主和从
#sentinel auth-pass <master_name> xxxxx

#发生切换以后执行的一个自定义脚本:如发邮件、vip切换等
##sentinel notification-script <master-name> <script-path>     ##不会执行,疑问?
#sentinel client-reconfig-script <master-name> <script-path>  ##这个会执行

例子:

port 20086

dir "/var/lib/sentinel_20086"

logfile "/var/log/redis/sentinel_20086.log"

daemonize yes

sentinel monitor T1 127.0.0.1 10086 2

sentinel down-after-milliseconds T1 15000

sentinel failover-timeout T1 120000

sentinel parallel-syncs T1 1

#发生切换以后执行的一个自定义脚本:如发邮件、vip切换等
#sentinel notification-script <master-name> <script-path>

主要配置sentinel monitor  主服务器的地址,其余配置按须要调整。

可添加 logfile 路径做为 sentinel 的日志文件。

关键配置:sentinel monitor T1 127.0.0.1 10086 2

三、启动命令

redis-sentinel  sentinel.conf 

注意:当一个master配置为须要密码才能链接时,客户端和slave在链接时都须要提供密码。master经过requirepass设置自身的密码,不提供密码没法链接到这个master。slave经过masterauth来设置访问master时的密码。客户端须要auth提供密码,可是当使用了sentinel时,
因为一个master可能会变成一个slave,一个slave也可能会变成master,因此须要同时设置上述两个配置项,而且sentinel须要链接master和slave,须要设置参数:sentinel auth-pass <master_name> xxxxx

四、验证

一、分别查看sentinel日志可看到以下记录

image

可看到+monitor master mymaster 192.168.244.128 6379 quorum 2

+sentinel sentinel f578550308896289052a62744d7fd711f8e19d3f 192.168.244.130 26379 @ mymaster 192.168.244.128 6379

+sentinel sentinel b1538910277b0df2ea52c653cb2eed2a521c6ca1 192.168.244.131 26379 @ mymaster 192.168.244.128 6379

以下说明sentinel集群启动成功

二、服务器info 命令查看信息

192.168.244.128

image

192.168.244.130

image

192.168.244.131

image

三、关闭主redis info命令查看

192.168.244.131 已经成为主服务器

image

192.168.244.130 已经成为131 的从服务器

image

四、能够查看主服务器停掉以后sentinel的日志是如何切换主备的


image

五、从新启动后的主服务器变成了从服务器

image

 

整理自:http://www.javashuo.com/article/p-trqnlfbk-bg.html

           http://www.javashuo.com/article/p-pfxbqtku-cd.html

相关文章
相关标签/搜索