RocketMQ作为国人开源的一款消息引擎,相对kafka也更加适合在线的业务场景,在业内使用的也是非常广泛,很多同学也是非常熟悉它及它的存储机制,所以这里不再对它的原理性东西作太多说明。

我们也知道,RocketMQ所有的数据如消息信息都是以文件形式保存到broker节点所在主机上指定的分区目录下,比如消息的数据都是保存在commitlog中,默认保存72小时(在磁盘使用率未达到阈值的情况下)会在指定时间清理过期数据,释放磁盘空间。

当然,如果消息量不大且所在磁盘的分区够大,我们可以增加消息的保存时间。但受限于磁盘大小,这个保存时间总归有限,如果消息比较重要,或者我们想保存的更久一些就需要一些其它方案解决。

我们线上的几个集群目前消息保存时间在2-3天,实在是磁盘空间大小有限,消息量相对不算小。比如,有个比较核心的集群,部署方式是6个高配物理机采用DLedger模式4主8从交叉部署,发送的tps在10000多,所以每个节点的日消息量目前应该是在600G吧。老大给我说他现在设置的线上保存时间是2天,业务量一直在增加,继续增长下去,就要设置保存1天了,目前每个节点的磁盘使用率将近50%,年初我搭建监控平台的时候,注意过还没这么高。

还有其它集群上的业务,有些业务相关开发人员想要他们消息保存7天甚至更久。

基于这些原因,所以我们也的确需要一种过期消息备份的解决方案。

解决思路

如果需要对过期消息进行备份,然后支持过期消息检索及重新消费的能力,我们想到的,常规的方案有如下两种:

  • 将发送到broker的消息持久化一份到第三方存储介质,如mysql
  • 备份将要过期的commitlog到其它地方,重新恢复

业内大厂是采用哪些更好的方案,时间问题也没有具体调研过,我不得而知。关于第一种方案,老大也跟我聊过,我是不倾向的,原因如下:

  • 我们的消息代理平台还没有建设出来,业务用的基本都是原生的,如果想要在消息生命周期中镜像一份出来到其它存储系统,在不改源码的情况下,确实没有很好的切入点
  • 依赖其它存储介质,复杂性,开发成本也高,我的开发时间也不充裕,短期内实现这个,有点难
  • 全量保存的话,消息体的减少很难有质的变化,当然可以在处理的时候,去掉一些元数据信息,消息体也可以压缩减少存储空间的占用,但无论存哪,质量守恒,不会换个地方,用的硬盘资源就能等比减少很多倍

当然,这种方案的好处也很明显,可以更精细化的控制保存时间及消息类别,设定对哪些topic或哪类消息的保存时限。另外如果我们的MQ代理层建设完,无论是RocketMQ还是kafka等都可以采用一种通用方案备份。

我目前主要采用第2种解决方案并进行实现,备份commitlog,支持检索和重新消费。主要思路就是,开发一个应用,备份集群里将要过期的commitlog到更大的磁盘空间的主机(一台主机,备份整个集群的数据,且硬件配置不需要太高,硬盘尽量大即可),并提供接口,支持检索消息。