Master-Slave模式下的消息同步

为了保证MQ的数据的不丢失,而且具备一定的高可用性,所以一般都是将Broker部署成 Master-Slave模式 ,也就是一个Master Broker 对应一个 Slave Broker。
然后Master需要在接收消息之后,将数据同步给Slave,这样一旦Master Broker关了,还有Slave上有一份数据。
image.png
消息同步策略: Slave Broker会不停的发送请求到Master Broker去拉取消息。
image.png

RocketMQ实现读写分离

Master Broker主要负责接收系统的消息写入,然后会同步给Slave Broker。
作为消费者的系统在获取消息的时候,是有可能从Master Broker或者Slave Broker获取消息的。

作为消费者的系统在获取消息的时候,会先发送请求到Master Broker上去,请求获取一批消息,此时Master Broker是会返回一批消息给消费者系统的。
然后Master Broker在返回消息给消费者系统的时候,会根据当时Master Broker的负载情况和Slave Broker的同步情况,向消费者系统建议下一次拉取消息的时候是从Master Broker拉取还是Slave Broker拉取。

  • 如果此时Master Broker负载很重,本身要抗10万写并发,却还要从Master Broker里拉取消息,给它加重负担,那肯定不合适。所以此时Master Broker就会建议从Salve Broker去拉取消息。
  • 又比如,此时Master Broker上已经写入100万条数据,结果Slave Broker因为一些原因,同步得特别慢,才同步了96万条数据,落后了整整4万条消息的同步,这个时候作为消费者系统可能都获取到96万条数据了,那么下次还是只能从Master Broker去拉取消息。因为Slave Broker同步太慢了,导致无法从Slave Broker里获取到最新的消息了。

image.png
所以,在写入消息的时候,通常来说是选择Master Broker去写入的。
但是在拉取消息的时候,有可能从Master Broker获取,也有可能从Slave Broker去获取,一切都根据当时的情况来定。

Slave Broker挂掉会造成的影响

Slave Broker挂掉的话,那么此时无论是消息的写入还是消息的拉取,都是可以从Master Broker去走,对整体运行不影响。只不过少了Slave Broker,会导致所有的读写压力都集中在Master Broker。

Master Broker挂掉会造成的影响

这个时候对消息的写入和获取都有一定的影响,但是其实本质上而言,Slave Broker也是跟Master Broker一样有一份数据在的,只不过Slave Broker上的数据可能有部分没有来得及从Master Broker同步。
在RocketMQ4.5版本之前,都是用Slave Broker同步数据,尽量保证数据不丢失,但是一旦Master故障了,Slave是没办法自动切换为Master的。所以在这种情况下,如果Master Broker宕机了,这时就得手动做一些运维操作,把Slave Broker重新修改一些配置,重启机器给调整为Master Broker,这种做法就会导致中间会有一段时间是不可用的。
所以, Master-Slave模式 不是彻底的高可用模式,没法实现自动把Slave切换为Master。

基于Dledger实现的Rocket高可用自动切换

Dledger是基于Raft协议实现的机制。
简单来说,把Dledger融入RocketMQ之后,就可以让一个Master Broker对应多个Slave Broker,也就是说一份数据可以有多个副本,比如一个Master Broker对应两个Slave Broker。
然后依然在Master和Slave之间进行数据同步。
image.png
此时一旦Master Broker宕机了,就可以在多个副本,也就是多个Slave Broker中,通过Dledger技术和Raft协议算法进行leader选举,直接将一个Slave Broker选举为新的Master Broker,然后新的Master Broker就可以对外提供服务了。
整个过程也许主要10秒或者几十秒的时间就可以完成。这样的话,就可以实现Master Broker挂掉之后,自动从多个Slave Broker中选举一个新的Master Broker,继续对外服务,一切都是自动的。
image.png
所以,在设计RocketMQ生产部署架构的时候,完全可以采用基于Dledger的部署方式,这样就可以让RocketMQ做到自动故障切换了。