当前业界几款主流的MQ消息队列采用的存储方式主要有以下三种方式。
目前业界较为常用的几款产品(RocketMQ / Kafka / RabbitMQ)均采用的是消息刷盘至所部署虚拟机/物理机的文件系统来做持久化
刷盘一般可以分为异步刷盘、同步刷盘两种模式
消息刷盘为消息存储提供了一种高效率、高可靠性和高性能的数据持久化方式。除非部署 MQ 机器本身或是本地磁盘挂了,否则一般是不会出现无法持久化的故障问题。
这类 MQ 一般会采用诸如 LevelDB 、RocksDB 和 Redis 来作为消息持久化的方式。
由于分布式缓存的读写能力要优于 DB ,所以在对消息的读写能力要求都不是比较高的情况下,采用这种方式倒也不失为一种可以替代的设计方案。
消息存储于分布式 KV 需要解决的问题在于如何保证 MQ 整体的可靠性。
Apache下开源的另外一款MQ—ActiveMQ(默认采用的KahaDB做消息存储)可选用 JDBC 的方式来做消息持久化,通过简单的 XML 配置信息即可实现JDBC消息存储。
由于,普通关系型数据库(如 MySQL )在单表数据量达到千万级别的情况下,其 IO 读写性能往往会出现瓶颈。因此,如果要选型或者自研一款性能强劲、吞吐量大、消息堆积能力突出的 MQ 消息队列,那么并不推荐采用关系型数据库作为消息持久化的方案。在可靠性方面,该种方案非常依赖 DB ,如果一旦 DB 出现故障,则 MQ 的消息就无法落盘存储会导致线上故障。
1:存储效率:文件系统 > 分布式 KV 存储 > 关系型数据库 DB
2:直接操作文件系统肯定是最快和最高效的,而关系型数据库 TPS 一般相比于分布式 KV 系统会更低一些
简略地说,关系型数据库本身也是一个需要读写文件 Server ,这时 MQ 作为 Client与其建立
连接并发送待持久化的消息数据,同时又需要依赖 DB 的事务等,这一系列操作都比较消耗性
能
3:MQ的存储方式如何取舍
如果追求高效的IO读写,那么选择操作文件系统会更加合适一些
如果从易于实现和快速集成来看,文件系统 < 分布式 KV 存储 < 关系型数据库 DB,但是性能
会下降很多。
从消息中间件的本身定义来考虑,应该尽量减少对于外部第三方中间件的依赖。