最近接手公司自己的mq,梳理了整体的架构,发现broker在扩展性方面,尤其是做HA的时候,存在难以扩展的问题。于是就想,我们在做架构设计的时候,在项目还没有开始之前,怎么能够尽可能提早的发现问题,而不是到了项目成熟期,要做一些诸如HA,扩容所容,高可用的时候才发现系统的架构原来不那么灵活。

注:如果不熟悉mq的一些基本概念,可以先找一些rocketmq的资料看看

当前Broker架构

可以看出来,broker主要有两部分构成:service层,store层。中间依赖于一个store interface做隔离,具体的store有两类:fileStore和dbStore。

这个架构图应该是做设计的时候我们都会想到的,我把它称为模块架构: 模块架构反应了项目由哪些模块组成,各个模块之间是如何关联的;模块架构体现了代码(功能)的隔离和复用;模块架构有单机版的,有分布式版的,公司发展的中后期,模块的架构越来越偏向于分布式。总体而言,模块架构主要反映了代码的组织形式。

当前broker架构的问题

通过上面的broker模块架构图,可以看出,设计者在最初的时候,考虑了隔离和复用,broker的逻辑在上层,下层隔离的存储,具体的存储可以分为文件存储和数据库存储。看到这里,还觉得这是一个不错的设计,但问题出在哪里呢?

问题的出现,是我们在做HA的时候,因为broker对消息的存储有极高的可靠性要求,所以要做HA。但是基于上面的架构做HA就郁闷了:

  • 数据库存储的HA的通过数据库本身的主备,这个时候,broker service应该是无状态的
  • 文件存储的HA需要通过复制来实现,这个时候,broker service是有状态的,因为文件是存储在具体的每一个broker上的

这个时候,在过来看上面的设计,就别扭了,因为数据库存储和文件存储的HA,扩容机制完全不一样,broker service没法达到复用的目的。

那么,我们怎么在开始做设计的时候就想到这些问题呢?我想了下,在做设计的时候,除了画系统的模块架构图之外,还需要画下面两张架构图:

系统部署架构图

先把目前broker的系统部署架构图画下来:

看完这张图,是不是觉得文件存储和数据库存储已经有差异了? 再看一张图

系统HA架构图

文件存储类型的HA:

可以看出,文件类型的broker在做HA的时候其实是很重的操作,作为备份节点的broker必须同步完数据,客户端才能做切换,关键是:客户端要知道消息是发送到哪个broker的,也就是说,对于文件存储类型,broker是有状态的,不能随便切换的

数据库存储类型的HA

可以看出,数据库类型的broker在做HA的时候完全依赖于数据库,而数据库可以通过主备的形式轻松实现HA,这个时候,broker要做到无状态,一旦某一个broker有问题,可以随别切到另一个broker进行容错,因为每一个broker都是通过集中式的存储来共享数据

通过系统的HA架构图,就完成可以看出来,文件存储和数据库存储类型,压根不是像最开始的模块架构图那样,表现出来的统一和完美,我们不能把这两个类型作为一个项目来部署,否则,越到后面越痛苦。

总结

总结下,我们在做设计的时候,可以画下面几张架构图:

  • 系统模块架构图:侧重于代码级别的隔离,复用和扩展
  • 系统部署架构图:侧重于系统各个模块在物理上的隔离和生命周期管理
  • 系统HA架构图:侧重于整个系统的实际场景下的扩容所容,高可靠,高可用的设计

切不可以只画第一张系统模块图,项目不是把代码模块设计好了就万事大吉的