rocketmq是我们常用的消息中间件之一,现在我们就来分析一下,它是如何存储和读取消息的。

rocketmq是把消息持久化在本地的文件系统的,所有的消息,都保存在commitLog文件中,这个文件是不区分topic或者messageQueue的,所有的消息,都是保存在一起,这个点跟常见的kafka不同,kafka不同的分区,是保存在不同的文件中的,但是也因此引发了别的问题,就是在分区特别多的时候,由于文件数量太多,导致数据的读取效率急速下降,一般在几十个分区左右,不建议使用过多的分区,但是rocketmq最多可以支持上万的topic,就是因为两者的文件存储不同。因为rocketmq文件存储使用的是同一个文件,所以消息的写入是顺序的,每来一个消息,写入文件尾就可以了,效率很快。

但是光使用一个commitLog文件,肯定是不行的,因为不同的消费者,消费的messageQueue不同(这个具体可以看rocketmq的消费模型),不能每次拉取消息时,服务端都要遍历commitLog,然后找到对应的消息返回,这样效率太低了,这个时候,rocketmq使用的就是ConsumeQueue文件,该文件可以理解为是逻辑上的队列,一个consumeQueue文件,对应一个服务端上的messageQueue,但是里面存储的不是真正的消息体,而是该MessageQueue里面消息存储在commitLog文件中的的位置,所以文件尺寸是很小的,实际情况下,大部分的consumeQueue都是能全部存入内存中的,也就是可以很快的知道该messageQueue中的下一条消息在commitLog的位置,再通过RandomAccessFile来实现随机读,同样可以达到很快的消息读取效率。

rocketchat 存 mongodb 聊天记录表 rocketmq 消息存储_文件存储

rocketmq的存储结构如图所示,producer发送消息到服务端之后,直接存储在commit Log文件中,同时根据消息的messageQueue信息,在对应的comsumeQueue文件的尾部,添加这条消息的记录,也就是在commitLog文件中的位置,不同的消费者,根据消费的MessageQueue,通过对应的ConsumeQueue获取消息位置,并获取消息。

总体来说,rocketmq是通过实现顺序读,随机写,来保证自己的效率的。