前面已经了解过的内容如下:
- 集群中的每个Master Broker只存储一部分消息,通过主从保证高可用;
- 所有Broker都要注册到NameServer上
- NameServer是可以集群部署的,拥有每个Broker的信息;
- Broker每隔30s向NameServer发一次心跳
- NameServer每隔10s检测一次Broker的心跳时间,120s没有发送的Broker就认定为宕机;
- 生产者通过pull拉取NameServer上的Broker信息去访问目标Broker
正题:
- Master Broker如何将消息同步到Slave Broker?
- RocketMQ的读写分离原理
- Slave Broker宕机后会怎么样?
- 手动实现故障转移?
- 基于Dledger实现自动故障转移?
1.RocketMQ主从架构
(1)Master-Slave模式实现高可用:
为了保证MQ的数据不丢失并具备一定的高可用性,所以一般都是将Broker部署成Master-Slave模式的,也就是一个Master Broker对应一个Slave Broker。
具体的实现就是Master需要在接收到消息之后,将数据同步给Slave,这样一旦Master Broker 挂了,还在Slave上有一份数据。
(2)Master-Slave数据同步方式:
RocketMQ在Master-Slave主从模式中,采取的是Slave Broker 不停的发送请求到Master Broker去拉取消息。
这种模式是Pull模式拉取消息。
2.不彻底的读写分离
2.1 读写分离的场景
(1)场景1:Master负载太高
当前场景中的Master Broker负载达到10WQPS,负担太高。此时Master Broker就会建议去Slave Broker中拉取消息。
(2)场景2:Slave同步太慢
从Master Broker同步100W条数据到Slave Broker,但同步太慢,系统在Slave Broker只拉取到96W条数据。此时Master Broker 会要求在Master Broker拉取最新的消息。
2.2 读写分离原理
RocketMQ在Master-Slave模式下,读写分离并不是绝对的。
消费者的系统在获取消息的时候有可能从Master Broker获取消息,也有可能从Slave Broker获取消息。
从Master Broker读取消息的过程:
作为消费者的系统在获取消息的时候会先发送请求到Master Broker上去,请求获取一批消息,此时Master Broker 是会返回一批消息给消费者系统的。
然后Master Broker在返回消息给消费者系统的时候,会根据当时Master Broker的负载情况和Slave Broker 的同步情况向消费者系统建议下一次拉取消息的时候是从Master Broker拉取还是Slave Broker拉取。
3.Slave Broker宕机后的影响
问题:如果Slave Broker挂掉了,会对整个系统有影响吗?
有一点,但影响不大。
因为消息写入全部是发送到Master Broker的,然后消息获取既可以走Master Broker,也可以走Slave Broker.。
如果Slave Broker挂了,那么此时无论是消息写入还是消息拉取,都可以继续从Master Broker去走,虽然会导致所有读写压力都集中在Master Broker上,但是对整体运行不影响。
4.手动故障转移
不彻底的高可用模式:
在RocketMQ 4.5 版本之前,如果Master Broker故障了,Slave是无法自动切换成Master的。
这种情况下,只能够手动做运维操作,将Slave Broker重新修改一些配置后,重启机器给调整为Master Broker.
这种Master-Slave模式不是彻底的高可用模式,因为没法实现自动把Slave切换为Master.
5.基于Dledger协议实现高可用
在RocketMQ 4.5之后,RocketMQ支持Dledger机制,该机制基于Raft协议实现的。
基于Dledger实现高可用原理:
把Dledger融入RocketMQ之后,就可以让一个Master Broker对应多个Slave Broker,也就是说一份数据可以有多分副本,比如一个Master Broker对应两个Slave Broker.
此时一旦Master Broker宕机了,就可以在多个副本,也就是多个Slave中,通过Dledger技术和Raft协议算法进行leader选举,直接将一个Slave Broker选举为新的Master Broker,然后这个新的Master Broker就可以对外提供服务了。
预计整个过程也行只要10秒或者几十秒的时间就可以完成。
6.思维扩散
(1) 4.5 版本之前,Master崩溃会造成多长时间的系统不可用?
这时候如何能够尽快的恢复集群运行?
依赖手工运维的话,如何能尽快的去完成这个运维操作?
答:系统不是不可用,是只能读取消息,不能继续生产消息。
尽快恢复就是写一个脚本,修改配置参数,然后进行重启,执行脚本。
最快的时间:采用的是Raft选举算法,强领导者模式,系统处于不可用状态,直到新的master被选举出来,系统才可用。
(2)4.5 版本之后,在Master崩溃直到新的Master被选举出来的过程中,对于使用MQ的系统而言,会处于什么状态?
在master宕机到重新弄选出master这段时间,对于写请求,系统是不可用的,对于读请求是可用的,但有一些数据可能未来得及同步到slave上,所以系统可能会有数据丢失。
(3)Kafka和RabbitMQ的多副本和高可用机制是什么样的?Kafka如何在集群维护多个副本?出现故障的时候能否实现自动切换?RabbitMQ是如何在集群理维护多个数据副本的?出现故障的时候能否实现自动切换?
答:kafka的高可用是消息分发到多个partition上,每个partition采取多副本机制,出现故障时可进行自动切换;rabbitmq是伪分布式高可用(镜像集群),集群中每个节点全部是一样的数据,没有副本机制,出现故障是没有转移机制,只是通过多实例集群来达到高可用目的。
(4)RocketMQ中Slave永远落后Master一些数据,这种主从不一致有没有什么问题?有什么办法保证主从数据强制一致吗?这样做又会有什么缺点?
答:主从同步,在主节点宕机时,还未来得及同步完数据,就会垂涎短暂数据不一致;如果出现脑裂时候,多台master就会出现一只主从数据不一致。如果想保证强一致性,配置参数,保证写入主节点的时候,必须同步完所有的slave,此时吞吐量会急剧下降,系统性能会有所降低。