仅供本人学习参考, 如有侵权, 请联系删除, 多谢!
sentinel可以让redis实现主从复制,当一个集群中的master失效之后,sentinel可以选举出一个新的master用于自动接替master的工作,集群中的其他redis服务器自动指向新的master同步数据.一般建议sentinel采取奇数台,防止某一台sentinel无法连接到master导致误切换.其结构如下:
例如下图所示:
在Server1 掉线后:
Sentinel状态持久化snetinel的状态会被持久化地写入sentinel的配置文件中.每次当收到一个新的配置时,或者新创建一个配置时,配置会被持久化到硬盘中,并带上配置的版本戳.这意味着,可以安全的停止和重启sentinel进程.
主观下线所谓主观下线(Subjectively Down, 简称 SDOWN)指的是单个Sentinel实例对服务器做出的下线判断,即单个sentinel认为某个服务下线(有可能是接收不到订阅,之间的网络不通等等原因).主观下线就是说如果服务器在down-after-milliseconds给定的毫秒数之内, 没有返回 Sentinel 发送的 PING 命令的回复, 或者返回一个错误, 那么 Sentinel 将这个服务器标记为主观下线(SDOWN ).sentinel会以每秒一次的频率向所有与其建立了命令连接的实例(master,从服务,其他sentinel)发ping命令,通过判断ping回复是有效回复,还是无效回复来判断实例时候在线(对该sentinel来说是"主观在线").sentinel配置文件中的down-after-milliseconds设置了判断主观下线的时间长度,如果实例在down-after-milliseconds毫秒内,返回的都是无效回复,那么sentinel回认为该实例已(主观)下线,修改其flags状态为SRI_S_DOWN.如果多个sentinel监视一个服务,有可能存在多个sentinel的down-after-milliseconds配置不同,这个在实际生产中要注意.
客观下线客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断,然后开启failover.客观下线就是说只有在足够数量的 Sentinel 都将一个服务器标记为主观下线之后, 服务器才会被标记为客观下线(ODOWN).只有当master被认定为客观下线时,才会发生故障迁移.当sentinel监视的某个服务主观下线后,sentinel会询问其它监视该服务的sentinel,看它们是否也认为该服务主观下线,接收到足够数量(这个值可以配置)的sentinel判断为主观下线,既任务该服务客观下线,并对其做故障转移操作.sentinel通过发送 SENTINEL is-master-down-by-addr ip port current_epoch runid,(ip:主观下线的服务id,port:主观下线的服务端口,current_epoch:sentinel的纪元,runid:*表示检测服务下线状态,如果是sentinel 运行id,表示用来选举领头sentinel)来询问其它sentinel是否同意服务下线.一个sentinel接收另一个sentinel发来的is-master-down-by-addr后,提取参数,根据ip和端口,检测该服务时候在该sentinel主观下线,并且回复is-master-down-by-addr,回复包含三个参数:down_state(1表示已下线,0表示未下线),leader_runid(领头sentinal id),leader_epoch(领头sentinel纪元).sentinel接收到回复后,根据配置设置的下线最小数量,达到这个值,既认为该服务客观下线.客观下线条件只适用于主服务器: 对于任何其他类型的 Redis 实例, Sentinel 在将它们判断为下线前不需要进行协商, 所以从服务器或者其他 Sentinel 永远不会达到客观下线条件.只要一个 Sentinel 发现某个主服务器进入了客观下线状态, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对失效的主服务器执行自动故障迁移操作.
在redis-sentinel的conf文件里有这么两个配置:1)sentinel monitor
四个参数含义:masterName这个是对某个master+slave组合的一个区分标识(一套sentinel是可以监听多套master+slave这样的组合的).ip 和 port 就是master节点的 ip 和 端口号.quorum这个参数是进行客观下线的一个依据,意思是至少有 quorum 个sentinel主观的认为这个master有故障,才会对这个master进行下线以及故障转移.因为有的时候,某个sentinel节点可能因为自身网络原因,导致无法连接master,而此时master并没有出现故障,所以这就需要多个sentinel都一致认为该master有问题,才可以进行下一步操作,这就保证了公平性和高可用.
主观下线(SDOWN)和客观下线(ODOWN)的更多细节sentinel对于不可用有两种不同的看法,一个叫主观不可用(SDOWN),另外一个叫客观不可用(ODOWN).SDOWN是sentinel自己主观上检测到的关于master的状态,ODOWN需要一定数量的sentinel达成一致意见才能认为一个master客观上已经宕掉,各个sentinel之间通过命令SENTINEL is_master_down_by_addr来获得其它sentinel对master的检测结果.从sentinel的角度来看,如果发送了PING心跳后,在一定时间内没有收到合法的回复,就达到了SDOWN的条件.这个时间在配置中通过is-master-down-after-milliseconds参数配置.当sentinel发送PING后,以下回复之一都被认为是合法的:PING replied with +PONG.PING replied with -LOADING error.PING replied with -MASTERDOWN error.其它任何回复(或者根本没有回复)都是不合法的.
从SDOWN切换到ODOWN不需要任何一致性算法,只需要一个gossip协议:如果一个sentinel收到了足够多的sentinel发来消息告诉它某个master已经down掉了,SDOWN状态就会变成ODOWN状态.如果之后master可用了,这个状态就会相应地被清理掉.正如之前已经解释过了,真正进行failover需要一个授权的过程,但是所有的failover都开始于一个ODOWN状态.ODOWN状态只适用于master,对于不是master的redis节点sentinel之间不需要任何协商,slaves和sentinel不会有ODOWN状态.
配置版本号为什么要先获得大多数sentinel的认可时才能真正去执行failover呢?当一个sentinel被授权后,它将会获得宕掉的master的一份最新配置版本号,当failover执行结束以后,这个版本号将会被用于最新的配置.因为大多数sentinel都已经知道该版本号已经被要执行failover的sentinel拿走了,所以其他的sentinel都不能再去使用这个版本号.这意味着,每次failover都会附带有一个独一无二的版本号.我们将会看到这样做的重要性.而且,sentinel集群都遵守一个规则:如果sentinel A推荐sentinel B去执行failover,B会等待一段时间后,自行再次去对同一个master执行failover,这个等待的时间是通过failover-timeout配置项去配置的.从这个规则可以看出,sentinel集群中的sentinel不会再同一时刻并发去failover同一个master,第一个进行failover的sentinel如果失败了,另外一个将会在一定时间内进行重新进行failover,以此类推.redis sentinel保证了活跃性:如果大多数sentinel能够互相通信,最终将会有一个被授权去进行failover.redis sentinel也保证了安全性:每个试图去failover同一个master的sentinel都会得到一个独一无二的版本号.
配置传播一旦一个sentinel成功地对一个master进行了failover,它将会把关于master的最新配置通过广播形式通知其它sentinel,其它的sentinel则更新对应master的配置.一个faiover要想被成功实行,sentinel必须能够向选为master的slave发送SLAVEOF NO ONE命令,然后能够通过INFO命令看到新master的配置信息.当将一个slave选举为master并发送SLAVEOF NO ONE后,即使其它的slave还没针对新master重新配置自己,failover也被认为是成功了的,然后所有sentinels将会发布新的配置信息.新配在集群中相互传播的方式,就是为什么我们需要当一个sentinel进行failover时必须被授权一个版本号的原因.每个sentinel使用##发布/订阅##的方式持续地传播master的配置版本信息,配置传播的##发布/订阅##管道是:__sentinel__:hello.因为每一个配置都有一个版本号,所以以版本号最大的那个为标准.
Redis Sentinel 是一个分布式系统, 可以在一个架构中运行多个 Sentinel 进程(progress), 这些进程使用流言协议(gossip protocols)来接收关于主服务器是否下线的信息, 并使用投票协议(agreement protocols)来决定是否执行自动故障迁移, 以及选择哪个从服务器作为新的主服务器.一个简单的主从结构加sentinel集群的架构图如下:
个人认为,Sentinel实现的最主要的一个功能就是能做到自动故障迁移,即当某一个master挂了的时候,可以自动的将某一个slave提升为新的master,且原master的所有slave也都自动的将自己的master改为新提升的master,这样我们的程序的可用性大大提高了.只要redis安装完成,Sentinel就安装完成了,Sentinel集成在redis里了.
每个 Sentinel 都需要定期执行的任务每个 Sentinel 以每秒钟一次的频率向它所知的主服务器、从服务器以及其他 Sentinel 实例发送一个 PING 命令.如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 那么这个实例会被 Sentinel 标记为主观下线. 一个有效回复可以是: +PONG 、 -LOADING 或者 -MASTERDOWN .如果一个主服务器被标记为主观下线, 那么正在监视这个主服务器的所有 Sentinel 要以每秒一次的频率确认主服务器的确进入了主观下线状态.如果一个主服务器被标记为主观下线, 并且有足够数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断, 那么这个主服务器被标记为客观下线.在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有主服务器和从服务器发送 INFO 命令. 当一个主服务器被 Sentinel 标记为客观下线时, Sentinel 向下线主服务器的所有从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次.当没有足够数量的 Sentinel 同意主服务器已经下线, 主服务器的客观下线状态就会被移除. 当主服务器重新向 Sentinel 的PING 命令返回有效回复时, 主服务器的主管下线状态就会被移除.
Sentinel之间和Slaves之间的自动发现机制虽然sentinel集群中各个sentinel都互相连接彼此来检查对方的可用性以及互相发送消息.但是你不用在任何一个sentinel配置任何其它的sentinel的节点.因为sentinel利用了master的发布/订阅机制去自动发现其它也监控了统一master的sentinel节点.通过向名为__sentinel__:hello的管道中发送消息来实现.同样,你也不需要在sentinel中配置某个master的所有slave的地址,sentinel会通过询问master来得到这些slave的地址的.每个sentinel通过向每个master和slave的发布/订阅频道__sentinel__:hello每秒发送一次消息,来宣布它的存在.每个sentinel也订阅了每个master和slave的频道__sentinel__:hello的内容,来发现未知的sentinel,当检测到了新的sentinel,则将其加入到自身维护的master监控列表中.每个sentinel发送的消息中也包含了其当前维护的最新的master配置.如果某个sentinel发现自己的配置版本低于接收到的配置版本,则会用新的配置更新自己的master配置.在为一个master添加一个新的sentinel前,sentinel总是检查是否已经有sentinel与新的sentinel的进程号或者是地址是一样的.如果是那样,这个sentinel将会被删除,而把新的sentinel添加上去.
删除旧master或者不可达slavesentinel永远会记录好一个Master的slaves,即使slave已经与组织失联好久了.这是很有用的,因为sentinel集群必须有能力把一个恢复可用的slave进行重新配置.并且,failover后,失效的master将会被标记为新master的一个slave,这样的话,当它变得可用时,就会从新master上复制数据.然后,有时候你想要永久地删除掉一个slave(有可能它曾经是个master),你只需要发送一个SENTINEL RESET master命令给所有的sentinels,它们将会更新列表里能够正确地复制master数据的slave.
一个频道能够接收和这个频道的名字相同的事件. 比如说, 名为 +sdown 的频道就可以接收所有实例进入主观下线(SDOWN)状态的事件.
注意, 当格式中包含 instance details 字样时, 表示频道所返回的信息中包含了以下用于识别目标实例的内容.
以下是所有可以收到的消息的消息格式,如果你订阅了所有消息的话.第一个单词是频道的名字,其它是数据的格式.注意:以下的instance details的格式是: @ 如果这个redis实例是一个master,那么@之后的消息就不会显示.
目前会存在该脚本被执行多次的问题,网上查找资料获得的解释是:脚本分为两个级别, SENTINEL_LEADER 和 SENTINEL_OBSERVER ,前者仅由领头 Sentinel 执行(一个 Sentinel),而后者由监视同一个 master 的所有 Sentinel 执行(多个 Sentinel).
Slave选举与优先级当一个sentinel准备好了要进行failover,并且收到了其他sentinel的授权,那么就需要选举出一个合适的slave来做为新的master.
如果一个slave与master失去联系超过10次,并且每次都超过了配置的最大失联时间(down-after-milliseconds),如果sentinel在进行failover时发现slave失联,那么这个slave就会被sentinel认为不适合用来做新master的.更严格的定义是,如果一个slave持续断开连接的时间超过(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state就会被认为失去选举资格.
一个redis无论是master还是slave,都必须在配置中指定一个slave优先级.要注意到master也是有可能通过failover变成slave的.如果一个redis的slave优先级配置为0,那么它将永远不会被选为master.但是它依然会从master哪里复制数据.
故障转移所谓故障转移就是当master宕机,选一个合适的slave来晋升为master的操作,redis-sentinel会自动完成这个,不需要我们手动来实现.
一次故障转移操作大致分为以下流程:发现主服务器已经进入客观下线状态.对我们的当前集群进行自增, 并尝试在这个集群中当选.如果当选失败, 那么在设定的故障迁移超时时间的两倍之后, 重新尝试当选. 如果当选成功, 那么执行以下步骤:选出一个从服务器,并将它升级为主服务器.向被选中的从服务器发送 SLAVEOF NO ONE 命令,让它转变为主服务器.通过发布与订阅功能, 将更新后的配置传播给所有其他 Sentinel , 其他 Sentinel 对它们自己的配置进行更新.向已下线主服务器的从服务器发送 SLAVEOF 命令, 让它们去复制新的主服务器.当所有从服务器都已经开始复制新的主服务器时, 领头 Sentinel 终止这次故障迁移操作.每当一个 Redis 实例被重新配置(reconfigured) —— 无论是被设置成主服务器、从服务器、又或者被设置成其他主服务器的从服务器 —— Sentinel 都会向被重新配置的实例发送一个 CONFIG REWRITE 命令, 从而确保这些配置会持久化在硬盘里.
Sentinel 使用以下规则来选择新的主服务器:在失效主服务器属下的从服务器当中, 那些被标记为主观下线、已断线、或者最后一次回复 PING 命令的时间大于五秒钟的从服务器都会被淘汰.在失效主服务器属下的从服务器当中, 那些与失效主服务器连接断开的时长超过 down-after 选项指定的时长十倍的从服务器都会被淘汰.在经历了以上两轮淘汰之后剩下来的从服务器中, 我们选出复制偏移量(replication offset)最大的那个从服务器作为新的主服务器; 如果复制偏移量不可用, 或者从服务器的复制偏移量相同, 那么带有最小运行 ID 的那个从服务器成为新的主服务器.
Sentinel 自动故障迁移的一致性特质Sentinel 自动故障迁移使用 Raft 算法来选举领头(leader) Sentinel , 从而确保在一个给定的纪元(epoch)里, 只有一个领头产生.
这表示在同一个纪元中, 不会有两个 Sentinel 同时被选中为领头, 并且各个 Sentinel 在同一个纪元中只会对一个领头进行投票.
更高的配置纪元总是优于较低的纪元, 所以呢每个 Sentinel 都会主动使用更新的纪元来代替自己的配置.
简单来说, 可以将 Sentinel 配置看作是一个带有版本号的状态. 一个状态会以最后写入者胜出(last-write-wins)的方式(也即是,最新的配置总是胜出)传播至所有其他 Sentinel .
举个例子, 当出现网络分割(network partitions)时, 一个 Sentinel 可能会包含了较旧的配置, 而当这个 Sentinel 接到其他 Sentinel 发来的版本更新的配置时, Sentinel 就会对自己的配置进行更新.
如果要在网络分割出现的情况下仍然保持一致性, 那么应该使用 min-slaves-to-write 选项, 让主服务器在连接的从实例少于给定数量时停止执行写操作, 与此同时, 应该在每个运行 Redis 主服务器或从服务器的机器上运行 Redis Sentinel 进程.
Sentinel 状态的持久化Sentinel 的状态会被持久化在 Sentinel 配置文件里面.每当 Sentinel 接收到一个新的配置, 或者当领头 Sentinel 为主服务器创建一个新的配置时, 这个配置会与配置纪元一起被保存到磁盘里面.这意味着停止和重启 Sentinel 进程都是安全的.
Sentinel 在非故障迁移的情况下对实例进行重新配置即使没有自动故障迁移操作在进行, Sentinel 总会尝试将当前的配置设置到被监视的实例上面. 特别是:
根据当前的配置, 如果一个从服务器被宣告为主服务器, 那么它会代替原有的主服务器, 成为新的主服务器, 并且成为原有主服务器的所有从服务器的复制对象.那些连接了错误主服务器的从服务器会被重新配置, 使得这些从服务器会去复制正确的主服务器.不过, 在以上这些条件满足之后, Sentinel 在对实例进行重新配置之前仍然会等待一段足够长的时间, 确保可以接收到其他 Sentinel 发来的配置更新, 从而避免自身因为保存了过期的配置而对实例进行了不必要的重新配置.
总结来说,故障转移分为三个步骤:
温馨提示:还可以向任意sentinel发生sentinel failover 进行手动故障转移,这样就不需要经过上述主客观和选举的过程.
sentinel.conf文件配置参数解释
基于以上细节知识梳理,总结出sentinel的工作原理
第二段:redis sentinel 主从切换(failover)的容灾环境部署记录
redis主从复制简单来说:A)Redis的复制功能是支持多个数据库之间的数据同步.一类是主数据库(master)一类是从数据库(slave),主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从数据库,而从数据库一般是只读的,并接收主数据库同步过来的数据,一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库.B)通过redis的复制功能可以很好的实现数据库的读写分离,提高服务器的负载能力.主数据库主要进行写操作,而从数据库负责读操作.
Redis主从复制流程简图
0)Redis主从结构支持一主多从+n个sentinel模式,信息如下:
a)redis服务器上各自存在一个Sentinel,监控本机redis的运行情况,并通知给闭路环上其它的redis节点;b)当master发生异常(例如:宕机和断电等)导致不可运行时,Sentinel将通知给其它节点,而剩余节点上的Sentinel将重新选举出新的master,而原来的master重新恢复正常后,则一直扮演slave角色;c)规定整个架构体系中,master提供读写服务,而slave只提供读取服务.
①.)redis一键安装(三个节点上都要操作)