当前位置: 首页 > 科技观察

分布式Redis深入历险-Sentinel

时间:2023-03-15 15:24:46 科技观察

试想一下,在一主一从或者一主多从的结构下,如果主服务器挂了,整个集群不可用,单点问题有没有得到解决。Redis使用Sentinel来解决这个问题,保证集群的高可用。如何保证集群的高可用要保证集群的高可用,必须具备以下能力:能够监控服务器的状态,当主服务器不可用时,能够及时发现当主服务器不可用时,选择一个最合适的从服务器代替原来的主服务器来存储相同的数据只有一台主服务器同时实现上述功能。最直观的方式是使用监控服务器来监控Redis服务器的状态。监控服务器与主从服务器之间保持心跳连接。当一定时间内没有收到主服务器的心跳时,主服务器会被标记为离线,然后通知从服务器上线成为主服务器。当原来的主服务器上线后,监控服务器会将其转换为从服务器。按照上面的流程,似乎已经解决了集群高可用的问题,但是好像哪里不对:如果监控服务器出现问题怎么办?我们可以添加一个从监控服务器,在主服务器不可用的时候补上。但问题是谁来监控‘监控服务器’?子子孙孙无穷无尽。.先放下疑惑,我们先看看RedisSentinel集群Sentinel的实现和上一节是一样的。Redis通过添加额外的Sentinel服务器来监控数据服务器。Sentinel将保存与所有主服务器和从服务器的连接。用于监视服务器状态并向服务器发出命令。Sentinel本身就是一个处于特殊状态的Redis服务器。启动命令:redis-server/xxx/sentinel.conf--sentinel,sentinel模式的启动过程与普通redisserver不同,比如不会加载RDB文件,AOF文件本身不存储业务数据.与主服务器建立连接Sentinel启动后,会与配置文件中提供的所有主服务器建立两个连接,一个是命令连接,一个是订阅连接。命令连接用于向服务器发送命令。订阅连接用于订阅服务端的_sentinel_:hello频道,获取其他Sentinel信息,下面会详细介绍。获取主服务器信息Sentinel会以一定的频率向主服务器发送Info命令来获取信息,包括主服务器自身的服务器id等信息,以及对应的从服务器信息,包括ip和端口。Sentinel会根据info命令返回的信息更新自己保存的服务器信息,并与从服务器建立连接。获取从服务器信息类似于与主服务器的交互。Sentinel也会以一定的频率通过Info命令获取从服务器的信息,包括:从服务器ID、从服务器与主服务器的连接状态、从服务器的优先级、从服务器的Copy偏移量等等。向服务器订阅和发布消息在如何保证集群高可用的部分留下了一个疑问:如何保证监控服务器的高可用?这里我们可以给出一个简单的答案:使用监控服务器集群(即Sentinel集群)。如何实现,如何保证监控服务器的一致性,暂且不谈。我们只需要记住,我们需要使用多个Sentinels来确保高可用性。一个哨兵如何感知其他哨兵?如前所述,Sentinels正在与服务器建立联系。连接时,会建立两个连接,其中一个是订阅连接。Sentinel会定时通过订阅连接向_sentinel_:hellochannel通道发送消息(对Redis发布订阅功能不太了解的同学可以了解一下),包括:Sentinel自己的信息,比如ip地址,端口号,configurationSentinel监控的主服务器的epoch等信息(见下),包括ip,端口,配置epoch(见下)等,同时Sentinel也会订阅_sentinel_:hello的消息channel,这意味着Sentinel将向channel发布消息,而channel又订阅来自该频道的消息。Sentinel有一个字典对象sentinels,它保存了监视同一主服务器的所有其他Sentinel服务器。当Sentinel从_sentinel_:hello通道收到消息时,它会首先比较是否是自己发送的消息,如果是则忽略。否则,sentinel中的内容将被更新,并与新的Sentinel建立连接。主观下线Sentinel默认每秒向所有连接的服务器(主服务器、从服务器、Sentinel服务器)发送一次PING命令。如果在down-after-milliseconds内没有收到有效的回复,Sentinel会把服务器标记为主观下线,也就是说Sentinel认为服务器已经下线了。需要注意的是,不同的Sentinels的down-after-milliseconds是可以不同的。客观下线为了保证服务器真正下线,当Sentinel将一个服务器标记为主观下线时,它会向其他Sentinel实例发送Sentinelis-master-down-by-addr命令,接收到该命令的Sentinel实例就会replythestatusofthemainserver,代表Sentinel与主服务器的连接状态。Sentinel会统计所有发出的Sentinelis-master-down-by-addr命令的响应,并统计同意下线的master服务器数量。如果数量超过一定的阈值,主服务器将被标记为客观地宕机。leaderSentinel的选举当一个Sentinel将一个主服务器标记为客观下线时,每个监控该服务器的Sentinel将通过Raft算法协商选举一个leaderSentinel。建议先阅读Raft算法基础知识,再阅读下文。规则:所有哨兵都有资格成为领军哨兵。Aftereachelection,nomatterwhethertheleadingSentineliselectedornot,theconfigurationerawillbe+1.在某个时代,每个哨兵都有机会投票给其他人。人们选举自己的Sentinel作为源Sentinel,需要投票的Sentinel称为目标Sentinel。每一个发现主服务器被标记为客观离线并且没有被其他哨兵要求投票的哨兵都会要求其他哨兵将自己设置为头部一旦目标哨兵在配置时代投票给某个哨兵(或自己),目标Sentinel会拒绝该命令,为它后面收到的命令投票,目标Sentinel会回复它选出的Sentinel的id,而当前配置epoch的源Sentinel收到请求投票的回复:如果配置reply的epoch与自己相同,则检查目标Sentinel选出的headSentinel是否是自己。如果一个Sentinel被超过半数的SentinelsSentinel设置为leader,那么这个Sentinel就被称为leaderSentinel。在一个配置epoch中只会选出一个head(因为一个head需要超过一半的支持)。如果在给定的时间内没有选出head,过段时间会重新选出(配置epochWill+1)大家还记得我们一开始提出的如何保证Redis服务器高可用的问题吗文章的?答案是使用若干个Sentinel服务器,并使用Raft共识算法来保证集群的高可用,只要Sentinel服务器有一半以上的节点,如果一切正常,则集群可用。failoverleaderSentinel会执行以下三个步骤进行failover:1.选择离线主服务器的所有从服务器中的一个作为新的主服务器2.将其他从服务器的主服务器设置为新的主服务器3.更改将离线主服务器的角色设置为从服务器,并将其主服务器设置为新的主服务器。当服务器再次上线时,它会继续作为从服务器工作。第一步选择一个新的master服务器的规则如下:1.过滤掉所有下线的从服务器2.过滤掉最近5秒内没有响应Sentinel命令的从服务器3.过滤掉那些已经下线的从服务器与原主服务器断开连接超过down-after-milliseconds*10从服务器4.按照从服务器的优先级排序,选择优先级最高的那个5.如果有多个从服务器具有相同的优先级,选择副本偏移量最大的6.如果上一步的服务器比较多,选择id最小的