redis高可用sentinel原理

来源:互联网 发布:社交网络电影 编辑:程序博客网 时间:2024/05/17 07:17
在我的电脑下面执行下面的操作构建一个高可用的redis主从集群.
启动两个实例:
1、nohup /usr/local/webserver/redis/src/redis-server /usr/local/webserver/redis/conf/redis_6380.conf &
2、nohup /usr/local/webserver/redis/src/redis-server /usr/local/webserver/redis/conf/redis_6379.conf &
3、6380设置为6379的slave, redis-cli -p 6380  ,  slaveof 127.0.0.1 6379
4、nohup /usr/local/webserver/redis/src/redis-sentinel /usr/local/webserver/redis/conf/sentinel_26379.conf &
     nohup /usr/local/webserver/redis/src/redis-sentinel /usr/local/webserver/redis/conf/sentinel_26380.conf &
     nohup /usr/local/webserver/redis/src/redis-sentinel /usr/local/webserver/redis/conf/sentinel_26381.conf &


官方解决方案:
     redis sentinel的主要功能点:
          1、监控Monitor,监控master和slave是否正常运行
          2、告警Notification,提醒系统管理员,监控的redis实例出现了问题
          3、自动切换 Automatic failover ,     如果集群中的master不能正常工作了,sentinel会开启一个failover进程,该进程会从选举一个从slave中选举出一个master ,其他slave会重新配置,并从新的master复制数据,同样的我们的WEB应用也需要改变连接实例。
          4、可提供配置configuration provider,客户端可以从redis获取到权威的redis实例信息,客户端可以从sentinel获得一个正常运行的主库,如果主库挂了,会把新的主库告知 客户端
     
     多实例redis进程的优点:
          1、由多个实例确定master不可用的时候,才认定master真的不可用,以减少错误保障的概率。
          2、即使有实例发生故障,sentinel仍然能够正常运行。
     
 下面以几个图来讲解一下几个重点:




sentinel的监听机制为:
Monitor:
Sentinel通过不断的发送PING命令到master来实现监听,如果master在配置文件中指定的时间不能返回以下任意一种信息:
PING replied with +PONG.
PING replied with -LOADING error.
PING replied with -MASTERDOWN error.
sentinel会认为master已经down了,这种down称为主观down,即SDOWN状态,还不足以发起failover进程。



再来看看各sentinel实例之间是如何进行自动发现的。

每个sentinel会向redis的__sentinel_:hello 信道中发送自己的信息,主库信息和本地主库配置的版本号,这就类似于把这些sentinel
实例拉成一个群进行沟通。自动发现主要是为了 sentinel之间可以自动发现,以及交换各个sentinel之前的配置版本信息,以便sentinel可以及时
拉取master实例的配置到本地,而不需要经常去拉取最新配置。


failover流程开启条件:
当monitor进程认为master不可达以后,状态变成SDOWN,主观不可用,然后通过 向各个sentinel实例发送命令:sentinel  is-master-down-by-addr xxx 来判断是否其他sentinel也认为master不可用,当赞成不可用的sentinel实例个数超过配置的数值大小,就会进行下一步操作,判断是否
有足够的sentinel存活(其实这一点的本质是为了避免sentinel的单点故障问题),如果仍然有超过半数的sentinel存活,那么failover就会启动。

failover流程开启过程:
1、failover启动
2、选举一个sentinel执行failover进程
3、选举一个slave作为新的master
     a、与master断开连接的次数。如果一个slave与master失去联系超过10次,并且每次都超过了配置的最大失联时间(down-after-milliseconds option),并且,如果sentinel在进行failover时发现slave失联,那么这个slave就会被sentinel认为不适合用来做新master的。
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
         b、Slave的优先级。
         c、数据复制的下标(用来评估slave当前拥有多少master的数据,尽量少的丢失数据)。
         d、进程ID较小的优先。
4、选举出slave之后,向slave发送SLAVE OF NO ONE命令,脱离之前的master,然后通过INFO拉取配置信息,修改sentinel本地的配置版本号(这样可以通知其他sentinel拉取 最新的配置)。
5、向其他slave发送slave of ip port命令,通知他们跟新的master进行replication


以上就是最主要的流程,几个比较重要的需要注意的是:
1、sentinel不会删除不可达的其他sentinel,这样是为了避免sentinel的单点故障问题。
2、sentinel不会删除down掉的master信息和slave信息,这样是为了在这些服务重启后能够及时重新加入集群,并从新的master复制数据,同时对比版本号,进行配置的更新。



推荐几篇文章写得很好,应该说是翻译得不错,是从redis官网翻译过来的sentinel集群的相关说明。
Redis Sentinel机制与用法(一)
Redis Sentinel机制与用法(二) 


----------------------------------下面是我从redis官网翻译过来的,水平有限,也没有时间检查,很多错误,暂时记录在下面---------------------
快速构建:
          说明:截止目前,redis sentinel已经叫做sentinel2了,因为它重写了以前的预测算法,让它更加强大和简单了。稍后再介绍这个
          从redis2.8以后稳定版的redis sentinel就可以运行了,新的开发版本在git中的unstable分支上,sentinel1在2.6版本以后提供的,已经
          过时,并不建议使用。

          1、启动
               使用redis-sentinel命令:
redis-sentinel /path/to/sentinel.conf
                使用redis-server命令:
redis-server /path/to/sentinel.conf --sentinel
          以上两种方法是一样的,只是下面一种可以指定配置文件,如果没有指定配置文件,redis会拒绝启动。
          sentinel默认监听端口为26379,因此你需要把你的防火墙打开,如果需要更安全的使用,你可以指定其他 sentinel实例的的ip,只允许这些ip来访问这个端口。


     2、部署redis sentinel之前我们来梳理一下redis sentinel工作流程和原理。
          部署sentinel最少需要三个sentinel实例。
          多个sentinel应该部署在互相不影响的物理机或者虚拟机上面,应该运行在不同的空间中。
          自动redis使用了异步同步以后,redis+sentinel的模式并不能够保证在发生错误的情况下,你的写入一定能够成功,但是它能够把数据丢失量控制在一个比较小的时间范围
           你需要确认客户端的版本是否支持sentinel,虽然大部分客户端都支持。
           你需要在测试甚至生产环境中进行多次测试,否则上线以后发现缺少配置或其他问题就太晚了
           sentinel ,docker中使用需要注意:  Docker performs port remapping, breaking Sentinel auto discovery of other Sentinel processes and the list of slaves for a master. Check the section about Sentinel and Docker later in this document for more information.(没看懂)


     sentinel配置
          
          以下是几个基本的配置
               
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1

sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5

第一条命令:
sentinel monitor <master-group-name> <ip> <port> <quorum>

第一个配置表示,指定需要监听的master的ip和端口, 为这个master取一个别名,然后配置在多少个sentinel都超时的时候可以执行切换
注意:quorum的意义:
     1、表示由多少个sentinel都表示master不可达的时候可以执行切换操作。
     2、然而这个参数只是用来确定master已经不可用了,要真正的执行这个操作还需要得到超过一半的sentinel实例支持。比如你有5个sentinel实例,有两个实例已经
认为master不可达了,这个时候sentinel会进行以下操作:a、其中一台sentinel会决定启动failover切换进程,b、如果这个时候有3个sentinel表示支持,failover进程会被启动。
     实际上,这就意味着当超过一半的的sentinel不可用的时候,不会启动failover进程,进行主从切换。

其他配置的格式都是下面这种:
sentinel <option_name> <master_name> <option_value>

down-after-milliseconds表示多少毫秒以后master没有响应认为已经down机
parallel-syncs 表示在执行主从切换的过程中,其他的从机从新的主机拉取数据同步,每次拉取的从机的数量,因为进行了主从切换,从机会先flushdb,清空所有数据,然后从主机获取RDB文件载入,因此会造成阻塞。如果该值过大,会导致很多同步时slave不可用。可以直接设置为1,每次只同步一台从机。

这些配置可以在客户端执行SENTINEL SET命令进行修改,方便不重启机器即修改配置。


搭建简单的sentinel集群:
说明:
     1、master直接使用M1,M2,M3..来进行代替
     2、slaves用R1,R2,R3...来代替(表示为replcation 复制)
     3、setinal实例用S1,S2,S3来进行代替
     4、clients客户端连接以C1,C2,C3...来代替进行说明

   例子一、搭建两个redis实例和两个sentinel实例(千万别这么做,这里只是讲解)
+----+         +----+
| M1 |---------| R1 |
| S1 |         | S2 |
+----+         +----+

Configuration: quorum = 1



     来看看以下几个场景:
     1、M1 挂掉以后,R1会被设置为master(quorum=1),failover进程启动,同时授权也会通过(两个S1,S2正常运行)
     2、如果机器1挂掉了,那么M1和S1都会停止运行,这个时候S2会尝试进行failover,但是由于S2不能得到超过一半的票数(可运行的sentinel不过半),因此不能将R2切换成master,集群变得不可用。所以还是希望尽量把sentinel和redis部署在不同的环境。

     
     例子二、非常简单的一个部署,三台机器,每个盒子运行一个redis实例和一个sentinel实例

       +----+
       | M1 |
       | S1 |
       +----+
          |
+----+    |    +----+
| R2 |----+----| R3 |
| S2 |         | S3 |
+----+         +----+

Configuration: quorum = 2
       来看看以下几个场景:
     1、M1服务挂掉,S1,S2,S3认定master不可达,failover启动,sentinel多票数通过,failover进程创建。服务可用
     2、M1机器挂掉,M1和S1都不可达,此时仍然存在超过半数的sentinel实例存在,sentinel可以启动failover

     再来看看下面这个场景
         +----+
         | M1 |
         | S1 | <- C1 (writes will be lost)
         +----+
            |
            /
            /
+------+    |    +----+
| [M2] |----+----| R3 |
| S2   |         | S3 |
+------+         +----+

       M1网络断开,R2通过sentinel的failover,自动切换成master,但是此时客户端的连接可能仍然是M1,那么这些写入操作的数据在网络恢复之前将无法获取。
     上面的这个问题可以通过redis主从复制的另外一个特性来进行解决,这个特性的原理是,redis的slave会不断的给主发送心跳包,如果超过
min-slaves-to-write 1
min-slaves-max-lag 10
          max-lag表示M多久没有收到心跳包认为S服务不可用。
          to-write表示当slave数量少于1(你配置的值)个的时候,将不会再允许写入操作。


     例子三、把sentinel放在客户端中。
          
            +----+         +----+
            | M1 |----+----| R1 |
            | S1 |    |    | S2 |
            +----+    |    +----+
                      |
         +------------+------------+
         |            |            |
         |            |            |
      +----+        +----+      +----+
      | C1 |        | C2 |      | C3 |
      | S1 |        | S2 |      | S3 |
      +----+        +----+      +----+

      Configuration: quorum = 2

     上面这种部署情况中,C1,C2,C2是客户端,但是也不完全是单一的客户端,     它更像一个服务应用,因为它包含了sentinel监控。
redis已经发布了集成sentinel的客户端https://redis.io/topics/sentinel-clients

     场景一、如果M1所在机器塌机,那么S1和M1都不可用,此时failover得到票数并启动,应用是可用的。
     场景二、如果此时网络发生问题,M1和S1所在的机器网络都不可达,那么redis主从服务都不可用。
     场景三、同样我们也会遇到例子二所说的问题,如果R1所在的网络不可达,在配置了min-slave时那么M1将无法写入,即使没有配置,
M1写入后也不能同步到slave,导致服务不可用。
     这种部署方案与案例二相比,他们有着相同的缺点,显然案例二更加容易管理。

下面快速简单的讲一下sentinel API,配置,语法,大部分都希望尽量快的的部署,这里部署3个sentianl实例

启动三个sentinel实例,端口号分别为5000,5001,5002
启动两个redis实例,分别为master和slave,端口号为6379,6380

三个sentinel实例的配置文件信息如下
port 5000
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1


三个sentinel启动的时候应该指定不同的端口,有些注意事项如下:
1、master实例别名为mymaster,你可以填写多个monitor,那这个sentinel实例就会监听多个主从集群
2、quorum的值我这里设置成为了2,因为我这里有三个sentinel实例。
3、这里down-after-milliseconds设置为了5000毫秒,即五秒,也就是说5秒内,sentinel的ping没有收到master返回的信息就认为不可达。



下面我们来看看如何通过sentinel获取信息:
1、连接5000端口的sentinel
redis-cli -p 5000
127.0.0.1:5000> sentinel master mymaster
 1) "name"
 2) "mymaster"
 3) "ip"
 4) "127.0.0.1"
 5) "port"
 6) "6379"
 7) "runid"
 8) "953ae6a589449c13ddefaee3538d356d287f509b"
 9) "flags"
10) "master"
11) "link-pending-commands"
12) "0"
13) "link-refcount"
14) "1"
15) "last-ping-sent"
16) "0"
17) "last-ok-ping-reply"
18) "735"
19) "last-ping-reply"
20) "735"
21) "down-after-milliseconds"
22) "5000"
23) "info-refresh"
24) "126"
25) "role-reported"
26) "master"
27) "role-reported-time"
28) "532439"
29) "config-epoch"
30) "1"
31) "num-slaves"
32) "1"
33) "num-other-sentinels"
34) "2"
35) "quorum"
36) "2"
37) "failover-timeout"
38) "60000"
39) "parallel-syncs"
40) "1"



我们可以看到,5000端口的sentinel实例已经发现了其他两个sentinel实例的存在, num-other-sentinels is 2
另外我们也可以看到flag参数为master,如果master挂掉了我们也可以看到s_down和o_down参数的存在
还有一个参数是slave的个数,同样我们也可以看到sentinel已经获取到了该master拥有的slave个数

如果我们需要查看slave的详细信息和其他sentinel的信息可以通过下面这个命令:
SENTINEL slaves mymaster
SENTINEL sentinels mymaster

获取当前master的地址我们可以通过下面这个命令,这样客户端就可以通过sentinel获取可用的master信息:
127.0.0.1:5000> SENTINEL get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6379"

下面我们来测试一下failover进程的运行:
测试failover进程的运行我们只需要让master在一定的时间内无法访问就可以了,执行下面的命令即可:
redis-cli -p 6379 DEBUG sleep 30

该命令可以让master sleep 30秒

然后我们来查看日志文件信息,发现failover经历了以下几个步骤:
1、每个sentinel都会给master标志一个sdown的状态, 意味着sentinel认为master down了
2、该标志马上升级成为odown,意味着多个sentinel都认为master已经不可达了
3、sentinel选取出一个实例, 进行failover操作
4、failover进程启动,发生主从切换


这个时候我们再通过命令行获取当前master信息:
127.0.0.1:5000> SENTINEL get-master-addr-by-name mymaster
1) "127.0.0.1"
2) "6380"


下面看看命令:
  • PING 这是一个ping/pong的心跳检测
  • SENTINEL masters 查看sentinel监听的所有redis master实例
  • SENTINEL master <master name>  指定查看具体master的状态
  • SENTINEL slaves <master name> 查看指定master拥有的slave实例的状态
  • SENTINEL sentinels <master name>  查看其它在监听该master实例的sentinel信息
  • SENTINEL get-master-addr-by-name <master name>  获取指定master的ip和port
  • SENTINEL failover <master name> 强制执行failover程序,该程序在master down的情况下,不需要过半的sentinel实例同意就可以执行,同样,sentinel的配置信息会进行更改。在sentinel实例 挂掉一般的情况下可以紧急使用。
  • SENTINEL ckquorum <master name> 检测有多少sentinel不可达master
  • SENTINEL flushconfig  强制把sentinel上下文中的配置信息写入到磁盘,该命令的用途是,当操作不当,把sentinel.conf文件删除了。

下面看看如何在运行时重新设置配置:
  • SENTINEL MONITOR <name> <ip> <port> <quorum>  添加一个新的master进行监听
  • SENTINEL REMOVE <name> 删除一个正在被监听的master
  • SENTINEL SET <name> <option> <value>  类似于redis的config set命令

比如设置mymaster的after-down时间:
SENTINEL SET mymaster down-after-milliseconds 1000


添加/删除一个sentinel
添加一个sentinel是非常简单的,因为sentinel实现了自动发现的机制,新增加的sentinel在10S钟之内就可以发现其他的sentinel以及master
拥有的所有slave信息
如果你一次性要添加多台sentinel,那还是非常建议你一台一台的添加,等待其他的sentinel都发现了新添加的sentinel后再添加下一台,这样做的
目的是为了避免在偶然的情况下,发生了master down,导致各sentinel的票数出现混乱的情况,导致failover失败。其实你也浪费不了太多时间,添加一个sentinel可能花费你仅仅30S的等待时间。添加完成后可以使用sentinel master [master-name]命令查看是否成功添加。


删除一个sentinel实例可能会稍微麻烦一点:因为sentinel在自动发现了其他sentinel以后并不会自动删除,即使这些sentinel已经不可达了,这也是
为什么在failover的时候需要过半的sentinel同意,这一点可以保证sentinel有至少过半的实例仍然可以正常运行。所以,删除一个sentinel实例你需要
做如下操作:
1、停止你需要移除的sentinel实例进程
2、去其他sentinel中执行sentinel reset [master-name] 删除sentinel所保存的信息,然后等待30S,让sentinel重新进行发现,建议一个一个的操作
3、检查,通过sentinel master [master-name]检查需要移除的sentinel是否真的已经移除


删除一个旧的master或者master不可达的slave实例(不是说client不可达的实例)
sentinel并不会自动剔除不可达的slave实例,这样做其实是非常有用的,
比如有几个slave所在的网络瘫痪,网络恢复以后,sentinel就可以快速的加入到slave中并返回给客户端。
比如master down以后重启成功,sentinel会迅速的把它加入到可用中,并成为一个新的slave
删除一个旧的master或者slave需要通过sentinel reset命令,通知所有的sentinal进行删除,删除完成以后请检查


从服务器的优先级
redis有一个slave-priority的参数,可以通过INFO命令查看 如果这个参数为0,那么该从服务器永远不会被升级成为master,
低优先级的slave被sentinal应该优先选中升级为master。详细的选举规则稍后将会讲到。


sentinal和redis的密码认证配置
主从配置:
     master中设置requirepass,slave中设置masterauth一致即可用。这貌似非常简单,但是在使用了sentinal之后就不一样了
 因为涉及到了切换,如果主库挂了,那么一个从库升级为主库,以前的主库恢复以后会从新主库同步数据。
这个切换其实不难。 因为sentinal只需要向所有的slave发送slave of命令并附带该slave的密码就可以了。但是逻辑操作比较多,
如果你希望一个slave不需要验证就可以使用,那么可以把slave-priority设置为0,这样该库不会被sentinal设置为主库,也不会有写入的风险




更多高级的特性:
SDOWN和ODOWN
sentinal对于master不可用有两种状态,第一种是SDOWN(主观不可用) ODOWN(客观不可用)。


下面再来看看sentinal是如何自动 发现slaves和其他sentinal的
sentinal可以自动发现master下的slave和其他正在监听该master的sentinal,但是你不用在配置文件里进行配置,sentinal使用了redis的
Pub/Sub(订阅发布机制)

slave的发现机制并不用讲太多,sentinal只需要发送一个INFO命令到redis客户端即可获取到该redis所拥有的slave的信息
主要来看看sentinal之前是如何自动发现的。
1、sentinal向所有的redis实例,包括master和多个slave,通过发送PUBLIC命令发布自己的ip,端口,进程ID,到 __sentinel__:hello这个信道。每2S发布一次。
2、同时,sentinal也会订阅所有redis实例的__sentinel__:hello信道,以此来发现是否有sentinal没有被发现,
3、同时hello这个信道的message也会包含master的所有配置信息,当其他sentinal收到这些信息以后会与本地的
配置信息进行比较,然后更新到最新的master配置。
4、在添加一个sentinal之前,同样也会检查runid,ip,端口等进行检查,以免出现相同的。




下面来看看sentinal如何进行配置文件的更新
即使不是在进行failover的时候,sentinel也会去更新slave的配置信息,以此来避免以下几个情况:
1、slave连接到了错误的master
2、slave断开了网络连接,重新连接以后配置信息已经过期了
3、down的master重启后,以slave的身份重新连接
你需要意识到的一点:sentinel会经常尝试着去拿一个合理的配置,然后保存在监控中。





failover是如何在slaves中通过priority进行选举的









     






































0 0
原创粉丝点击