1、本地消息队列集群
对于本地消息队列,主备之间同步可以使用同步刷盘、同步双写、异步复制等方式,这些功能一般已经内置在消息队列组件中。
2、跨地域消息队列集群
但是对于异地多活消息队列来说,网络延时是一个不可忽视的因素,所以同步刷盘、同步双写等策略已不再适用。而对于异步复制的方式虽然可用,但是会使得跨数据中心的多个消息队列集群耦合程度过高,拓扑结构更加复杂。就RocketMQ来说,RocketMQ的Broker是多主多从结构,主负责读写请求,而从负责读请求,各地域之间两两互为主备,但是这会使得网络结构非常复杂,并且几乎每个消息的消费都需要跨地域(普通消息消费以后需要上报逻辑消费点位到Master),代价太高。
3、基于事件总线的异地多活集群
因此在实现上,倾向于各个数据中心独立部署本地消息队列,然后通过消息同步服务,对各个数据中心的数据进行两两间的双向同步,网络结构大大简化。
实现消息队列异地多活的一个关键组件是事件总线/消息同步服务,在其它的实现中,提供了一个中心化的事件总线,通过专线网络接入多个数据中心,使用CloudEvents协议,实现各数据中心间数据双向同步。
4、去中心化星状异地多活集群
但是对于非云应用的异地多活方案来说,存在这样一个中心化的组件则会为实施带来额外的难度,因此可以考虑使用消息同步组件代替事件总线,该组件从注册中心中感知其它数据中心,并且选取其中一个作为主数据中心与其它数据中心进行双向同步。形成一个星状的异地多活集群。
在这种架构下,每个数据中心的消息队列同步服务注册到配置中心并获取元数据配置关系,一方面通过消息同步服务同步本地产生的消息数据以及逻辑消费点位到主数据中心,另一方面接收到消息之后,直接写入本地消息队列(后续在进行流量切换的时候需要重置逻辑消费点位,或者按另一种方案先写入临时消息队列进行存储,等待逻辑消费点位到达该消息之后再将该消息写入目标队列),对于作为主数据中心的消息同步服务,还需要将接收到的消息再投递到其它数据中心。
5、数据环回问题
架构确定之后,还需要解决数据环回问题,这个比较容易,只需要给每条消息的ID都打上数据中心标记,然后在往目标数据中心同步数据时将从目标数据中心接收到的消息排除在外即可。