RabbitMQ集群恢复与故障转移的5种解决方案

RabbitMQ集群恢复与故障转移的5种解决方案,第1张

前提:比如两个节点A和B组成一个镜像队列

场景1: A先停, B后停

方案1: 该场景下B是Master,只要先启动B,再启动A即可。或者先启动A,再30秒之内启动B接口恢复镜像队列

场景2: A、B同时停机

方案2:该场景可能由于机房断电等原因造成的,只需在30秒之内连续启动A和B即可恢复镜像

场景3:A先停,B后停,且A无法恢复

方案3: 该场景是1场景的加强版,因为B是Master,所以等B起来以后,在B节点调用控制台命令: rabbitmqctl forget_cluster_node A 解除与A的Cluster关系,再将新的Slave节点加入B即可重新恢复镜像队列

场景4: A先停,B后停,且B无法恢复

方案4:该场景是场景3的加强版,比较难处理,原因是因为Master节点无法恢复,早在3.1x时代之前没有什么好的解决方案,但是现在已经有解决方案了,在3.4.2以后的版本。因为B是主节点,所有直接启动A是不行的,当A无法启动的时候,也就没办法在A节点上调用之前的 rabbitmqctl forget_cluster_node B 命令了。新版本中 forget_cluster_node 支持--offline参数

这就意味着允许rabbitmqctl在理想节点上执行该命令,迫使RabbitMQ在未启动Slave节点中选择一个节点作为Master。当在A节点执行 rabbitmqctl forget_cluster_node --offline B 时,RabbitMQ会mock一个节点代表A,执行 forget_cluster_node 命令将B剔除cluster,然后A就可以正常的启动了,最后将新的Slave节点加入A即可恢复镜像队列

场景5:A先停、B后停,且A、B均无法恢复,但是能得到A或B的磁盘文件

方案5:这种场景更加难处理,只能通过恢复数据的方式去尝试恢复,将A与B的数据文件模式在$RABBIT_HOME/var/lib/目录中,把它拷贝到新的节点对应的mulxia,再将新的节点hostname改成A或B的hostname,如果是A节点(Slave)的磁盘文件,则按照场景4处理即可,如果是B节点(Master)的磁盘文件,则按照场景3处理即可,最后新的Slave加入新节点后完成恢复。

场景6:A先停、B后停,且A、B均无法恢复,且得不到A和B的磁盘文件

恩,你可以直接跑路了o(╯□╰)o

信息粒度是反映信息详细程度的概念。为适应不同子系统信息需求的详细程度不同.

知识的粒度用来描述使用该知识对论域划分的分类情况。

下面就我具体讲一下关于粒度测试方面的基知识和基本方法。

粒度测试是通过特定的仪器和方法对粉体粒度特性进行表征的一项实验工作。粉体在我们日常生活和工农业生产中的应用非常广泛。如面粉、水泥、塑料、造纸、橡胶、陶瓷、药品等等。在的不同应用领域中,对粉体特性的要求是各不相同的,在所有反映粉体特性的指标中,粒度分布是所有应用领域中最受关注的一项指标。所以客观真实地反映粉体的粒度分布是一项非常重要的工作。

一、粒度测试的基本知识

1、颗粒:在一尺寸范围内具有特定形状的几何体。这里所说的一尺寸一般在毫米到纳米之间,颗粒不仅指固体颗粒,还有雾滴、油珠等液体颗粒。

2、粉休:由大量的不同尺寸的颗粒组成的颗粒群。

3、粒度:颗粒的大小叫做颗粒的粒度。

4、粒度分布:用特定的仪器和方法反映出的不同粒径颗粒占粉体总量的百分数。有区间分布和累计分布两种形式。区间分布又称为微分分布或频率分布,它表示一系列粒径区间中颗粒的百分含量。累计分布也叫积分分布,它表示小于或大于某粒径颗粒的百分含量。

5、粒度分布的表示方法:

① 表格法:用表格的方法将粒径区间分布、累计分布一一列出的方法。

② 图形法:在直角标系中用直方图和曲线等形式表示粒度分布的方法。

③ 函数法:用数学函数表示粒度分布的方法。这种方法一般在理论研究时用。如著名的Rosin-Rammler分布就是函数分布。

6、粒径和等效粒径:

粒径就是颗粒直径。这概念是很简单明确的,那么什么是等效粒径呢,粒径和等效粒径有什么关系呢?我们知道,只有圆球体才有直径,其它形状的几何体是没有直径的,而组成粉体的颗粒又绝大多数不是圆球形的,而是各种各样不规则形状的,有片状的、针状的、多棱状的等等。这些复杂形状的颗粒从理论上讲是不能直接用直径这个概念来表示它的大小的。而在实际工作中直径是描述一个颗粒大小的最直观、最简单的一个量,我们又希望能用这样的一个量来描述颗粒大小,所以在粒度测试的实践中的我们引入了等效粒径这个概念。

等效粒径是指当一个颗粒的某一物理特性与同质的球形颗粒相同或相近时,我们就用该球形颗粒的直径来代表这个实际颗粒的直径。那么这个球形颗粒的粒径就是该实际颗粒的等效粒径。等效粒径具体有如下几种:

① 等效体积径:与实际颗粒体积相同的球的直径。一般认为激光法所测的直径为等效体积径。

② 等效沉速径:在相同条件下与实际颗粒沉降速度相同的球的直径。沉降法所测的粒径为等效沉速径,又叫Stokes径。

③ 等效电阻径:在相同条件下与实际颗粒产生相同电阻效果的球形颗粒的直径。库尔特法所测的粒径为等效电阻径。

④ 等效投进面积径:与实际颗粒投进面积相同的球形颗粒的直径。显向镜法和图像法所测的粒径大多是等效投影面积直径。

7、表示粒度特性的几个关键指标:

① D50:一个样品的累计粒度分布百分数达到50%时所对应的粒径。它的物理意义是粒径大于它的颗粒占50%,小于它的颗粒也占50%,D50也叫中位径或中值粒径。D50常用来表示粉体的平均粒度。

② D97:一个样品的累计粒度分布数达到97%时所对应的粒径。它的物理意义是粒径小于它的的颗粒占97%。D97常用来表示粉体粗端的粒度指标。

其它如D16、D90等参数的定义与物理意义与D97相似。

③ 比表面积:单位重量的颗粒的表面积之和。比表面积的单位为m2/kg或cm2/g。比表面积与粒度有一定的关系,粒度越细,比表面积越大,但这种关系并不一定是正比关系。

8、粒度测试的重复性:同一个样品多次测量结果之间的偏差。重复性指标是衡量一个粒度测试仪器和方法好坏的最重要的指标。它的计算方法是:

其中,n为测量次数(一般n>=10);

x i为每次测试结果的典型值(一般为D50值);

x为多次测试结果典型值的平均值;

σ为标准差;

δ为重复性相对误差。

影响粒度测试重复性有仪器和方法本身的因素;样品制备方面的因素;环境与操作方面的因素等。粒度测试应具有良好的重复性是对仪器和操作人员的基本要求。

9、粒度测试的真实性:

通常的测量仪器都有准确性方面的指标。由于粒度测试的特殊性,通常用真实性来表示准确性方面的含义。由于粒度测试所测得的粒径为等效粒径,对同一个颗粒,不同的等效方法可能会得到不同的等效粒径。

可见,由于测量方法不同,同一个颗粒得到了两个不同的结果。也就是说,一个不规则形状的颗粒,如果用一个数值来表示它的大小时,这个数值不是唯一的,而是有一系列的数值。而每一种测试方法的都是针对颗粒的某一个特定方面进行的,所得到的数值是所有能表示颗粒大小的一系列数值中的一个,所以相同样品用不同的粒度测试方法得到的结果有所不同的是客观原因造成的。颗粒的形状越复杂,不同测试方法的结果相差越大。但这并不意味着粒度测试结果可以漫无边际,而恰恰应具有一定的真实性,就是应比较真实地反映样品的实际粒度分布。真实性目前还没有严格的标准,是一个定性的概念。但有些现象可以做为测试结果真实性好坏的依据。比如仪器对标准样的测量结果应在标称值允许的误差范围内;经粉碎后的样品应比粉粉碎前更细;经分级后的样品的大颗粒含量应减少;结果与行业标准或公认的方法一致等。

本文基于对redis、zookpeer、rocketmq、elasticsearch学习总结,对于分布式系统学习,一定绕不开一个点,那就是CAP定理。什么是CAP定理,我这里简单的复制摘抄一下百度上的文案。

CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

说明一下上面的三个要素各代表的含义:

CAP定理说明上述的三个要素不能兼顾,最多只能满足其中的两个要素,在分布式系统中,一般都是保证分区容错性,而在一致性和可用性之间做取舍。因此存在CP、AP两种分布式集群的实现。

CP集群,即满足一致性和分区容错性,如zookpeer

AP集群,即满足可用性和分区容错性,如redis-cluster

下面,针对与上述的CP和AP问题,我们展开话题。

对于分布式系统,学习了解多了之后,发现其内在的解决方案基本上都是一样的,所谓万变不离其中。总结一下大体在于以下几步:

数据分片,很多分布式系统尤其是中间件服务,一般都会涉及高并发,数据量大的问题,如redis-cluster、recketmq,以及被大家熟知的Elasticsearch。针对于大数据量高并发的问题,若不做处理,服务器的性能将会成为服务的瓶颈,解决的方案之一便是数据分片,将大数据量在集群中按照一定的规则分片,使数据按照一定的规则分布集群的不同服务器上,以减轻单个服务器的压力,保证服务集群的可用性。

redis-cluster的数据分片是通过redis-cluster的哈希槽来实现的,redis-cluster有16384个哈希槽,这个数量是固定的,根据集群中服务器的数量可以手动的调配每个服务上存放的hash槽的数量,哈希槽之间是相互独立的,因此对集群的扩展提供了便利。

rocketmq的分片和topic紧密相关,在使用rocketmq中,无论是消息的生产者还是消费者都需要注册订阅一个topic。在rocketmq集群中,集群中的broker保存这个topic下数据的一部分,也就是topic的其中一个数据分片。当然,rocketmq不仅将一个topic下的数据分片到多个broker上,而且,一个broker上的topic数据还可以被分为多个queue,这是因为rocketmq中,一个queue只能被一个consumer消费,若是consumer的数量多于queue的数量,没有绑定queue的consumer将不能消费数据。

elasticsearch的数据分片在我看来和mysql的分库分表原理是一样的,elasticsearch中,每一个索引都相当于mysql的一个表,将一个索引分成多个shard放在不同的节点上,每个shard存储一部分数据。elasticsearch将数据进行分片,这样可以支持集群的横向扩展,同时,多个节点提供服务可以提高系统的效率和吞吐量。

综上所述,数据分片的一般都有两个好处,一个是支持集群的横向扩展,而是提升服务的吞吐量和性能。数据分片解决了以上两个问题,但是若是集群中一个节点发生宕机,或者因为网络原因和集群断开链接,那么这部分的数据分片甚至整个集群都会不可用,如何解决这个问题,就需要用到数据备份和主备切换。

数据分片的策略 了解了数据分片之后,需要了解以下数据分片的策略,根据集群提供服务的性质不同,可以采用的数据分片策略也各有不同,下面是我学习后的总结:

说到这里,会发现其实这种分片策略和负载均衡的策略还是挺相似的。

数据备份,举个例子来说,我有两台电脑A、电脑B,A用于工作,B用于游戏,我写了一篇文章,保存在电脑上电脑上,若是某一天我的电脑A磁盘坏了,那我这篇文章就找不到了,即便我现在还有电脑B,我也没有办法在对文章进行编辑。但是若是我在之前,就将文章拷贝了一份放在电脑B上,那么现在,我用电脑B就可以对文件进行编辑修改。

举这个例子,我的目的就是为了说明数据备份对于集群可用性的意义,例子中,我的两台电脑可以认为是集群中两台服务器,两台服务器一开始提供的服务可能不相同,A电脑提供的就是编辑文章的服务,数据备份的意义就在于,当原本提供服务的服务器宕机损坏,集群中另外的服务器仍然可以根据已经备份的数据提供相同的服务,而不会影响到用户的工作。

数据备份的目的就是不发生单点问题的措施之一,但是若是数据备份的策略不合适,备份的时机不对,那么备份的数据时效性也是问题。还是从例子出发,这里的文章每次都是我手动从A电脑拷贝到B电脑,这是我的备份策略,若是我选择每天晚上才拷贝一次,那么若是A电脑在我拷贝之前坏了,当天的文章编辑数据就丢失了,采用手动的方式备份,这种备份方式耗时耗力且不可控,而在分布式集群中,不同的系统采用了不同的备份策略,下面一一来说明。

首先明确一点,在分布式集群中,不可能采用人工手动备份,一定是系统程序按照一定的规则自动备份,就好像我将AB连在一起,写个程序,让A电脑自动把文章同步到B电脑。数据备份的方式分为两种:

这里以redis-cluster和zookeeper举例。

在redis-cluster中,当一台新的slave节点加入时,会出发数据同步,需要将主节点的数据同步到从节点。这时根据从节点的状态有两种同步方案:完整重同步 和 部分重同步

完整重同步既是将主节点的全部数据都复制给新的slave节点。大致流程为,当一个新的节点加入进来时,发送PSYNC命令给主节点并携带slave节点自身的信息(重点是复制偏移量),主节点会根据slave传过来的信息判断是完整重同步还是部分重同步,如何判断与数据同步时的复制缓冲区有关,更细节不展开介绍。

相对于redis-cluster,zookeeper中的数据同步有四种方式,和redis-cluster完整重同步和部分重同步相似的SNAP(全量同步)和DIFF(增量同步),以及zk事务处理相关的TRUNC(仅回滚同步)、TRUNC+DIFF(回滚+增量同步)

当节点已经加入集群,成为集群中的从节点,只要不断开连接,一般都只需要进行增量同步,不过系统同步的范围和方式有所差异,大致分为下面六种:

下面还是以具体服务来举例: redis-cluster中,主从复制采用的是异步复制的方式,master节点在做数据变更之后,会由一个异步线程将数据变更同步给slave节点,这是通过push的方式。当redis2.8之后,slave会周期的获取最新的数据,加入了pull方式。无论是master还是slave,在进行数据同步时,不会阻塞正常的应用请求。所以redis-cluster的主从复制,是异步备份+最终一致性的备份。

elasticsearch的主从复制可以手动设置同步备份或者异步备份,数据备份时不要求强一致性,而是主分片(primary shard)会维护一份需要同步的(replica shard)分片列表,这个分片列表同步完成,则认为数据备份完成,需要注意的是,这里的主从复制不是节点的更新数据,而是分片的更新数据。

rocketmq的主从复制和elasticsearch类似,也可以分为同步备份和异步备份,不同的是rocketetmq的数据备份采用的是pull的方式,从节点会通过HAConnection链接主动向主节点发送待拉取数据偏移量,待主节点返回节点更新数据信息,更新从节点数据偏移量,如此重复。

zookeeper的数据备份则是通过ZAB协议,通过消息广播的方式同步数据到从节点。

当数据备份后,主从节点上就有了相同的数据,为了提升服务的性能,那么可以采用读写分离的方式。主节点提供数据写服务,从节点提供读服务,可以有效的分担主节点的服务器压力。可以进行数据分片的系统,如:redis、rocketmq、elasticsearch,一般都可以配置一主多从、多主多从的集群架构。

读写分离之后,主节点提供写服务,从节点只提供读服务,因此若是主节点发生宕机,从节点依然可以提供读服务,但是服务无法更新数据,这时候就要进行主从切换。早起,主从切换可以由人工手动完成,不过随着技术发展,主从切换已经成为集群的必备功能。想要实现主从切换,必须要解决两个问题:

解决这个问题,需要额外再引入一个角色,相当于是一个监视者的角色,能够长期的对主节点进行监视,若是只有一个监视者,可能会发生误判,所以还需要一套机制去保证当监视者说主节点宕机,那么主节点是真的宕机,否则集群会出现脑裂问题。

以redis为例,在redis的哨兵模式中,这个监视者的角色是一个个哨兵实例,而在redis-cluster架构中,这个监视者的角色是redis实例自己。

在redis哨兵模式中,哨兵集群中的哨兵实例会定期和redis实例进行通信(ping),监视redis实例的在线情况,若是其中一台哨兵发现redis实例master故障,那么该哨兵会将该master状态改为主观下线,并通知其他哨兵,当哨兵集群中达到配置数量的哨兵实例认为该master都为主观下线状态,这时会将master修改为客观下线状态,并开始触发后续的故障转移。

在redis-cluster模式中,集群中的每一个节点都可以和其他节点通讯(ping),当某一个节点A发现主节点B下线了,A会将该主节点B设为疑似下线状态。集群中的节点会通过互发消息维护信息,当另一个节点C收到A的消息时,会将A对B节点的判断记录在C节点的维护信息下,这个信息可以理解为A说C疑似下线了。若是有其他节点发送C的状态信息,A同样也会记录。当某一个节点如C发现记录的B节点信息中,超过半数的主节点都认为B下线了,那么C就会将B节点状态修改为已下线状态,并广播消息给集群的其他节点,开始后续的故障转移。

上面就是redis的两种分布式模式故障检测的方案。大致可以归结为,监视节点会和被监视节点进行通讯,感知被监视节点的状态;监视节点之间也会进行通讯,同步信息。为了防止集群出现脑裂,对于某个主节点的故障判断会十分的谨慎,需要达到一定数量的监视节点都认为主节点故障时,才会认为主节点真的故障,从而触发故障转移。

在rocketmq集群模式中,nameserver扮演着监视者的角色(不同于其他系统,nameserver并不负责集群的主从切换,rocketmq 4.5之前不支持自动主从切换,4.5之后,通过dledger实现自动的故障转移)。在elasticsearch集群中,elasticsearch实例本身在扮演监视者角色。zookeeper也是实例本身扮演监视者的角色。

故障转移就是当集群发现集群中的主节点/从节点发生故障之后的处理,从节点比较简单,直接将从节点下线即可,主节点的故障转移流程比较复杂,各个系统根据系统的功能和架构有不同的实现方式,共同点是选举出的主节点一定是集群中数据最新的最完善的节点。

选举过程大致如下:

首先选举成功的条件时集群中具有投票权限的超过半数的节点投票一致,通过某一个节点成为主节点。

开始一轮选举时,定义为一个纪元,用一个自增的id表示。

候选节点将带着纪元id,以及自身信息作为投票申请广播给集群给可投票的节点。

具有投票权限的节点投票只要满足两个条件:1.自身在最新纪元没有给投过票 2.节点发送过来的投票申请时最新纪元的(如何判断时最新纪元,则是判断一下节点之前通过申请的纪元id是否小于当前申请的纪元id)。

半数以上的投票节点通过某一个候选节点成为leader节点,则leader产生。

若是一个纪元没有产生主节点,则候选节点进入随机的休眠,并且开启下一个纪元,知道产生leader节点。

在zk集群经过崩溃恢复模式之后,需要保证:1.已经提交的事务不能丢失 2.未被提交的事务不能出现。如何保证以上两点,zk服务集群中维护了zxid,zxid也可以看作是一个自增的id,集群中每产生一个新事物,zxid就会增加。zxid有64位,前32位维护了集群主节点变更情况,每重新选举出一个新的主节点则增加,后32位维护在新的主节点集群下事务的id,产生一个新事物则增加。

ZAB的选举模式有很多种,我主要了解了默认,也是推荐的FastLeaderElection模式,在这个模式下,我会以集群中一台参与选举的服务器的视角来模拟选主的过程;

我是一台zk服务器,我现在很慌,因为我的leader服务器不见了,作为一个有梦想的follower,我也要参加leader的选举,为了这次选举我要准备:myid(在集群中标识是这台服务器的id),zxid(本台服务器保存的最新事务id),logicClock(本台服务器发起的第几轮投票)

首先我会自己选自己,这得自信。于是我将自身的选举信息[myid, zxid]放到自己的收票箱,然后将我的选举信息还有我的选举轮次logicClock广播给其他服务器进行PK

作为一个有原则的服务器,我们的选举也是有原则的,当我收到别人的选举信息时,我也会将他和我自己的选举信息进行PK,PK的原则如下:

经过这一系列的PK,终于选出了我心中的leader服务器,要广播给其他服务器。

超过半数的服务器都同意某一台服务器成为leader,选举结束了。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/241111.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-12
下一篇2023-04-12

发表评论

登录后才能评论

评论列表(0条)

    保存