ActiveMQ 的持久化方式
一、需要进行消息持久化的原因
原因:
为了避免以外宕机以后丢失信息,需要做到重启之后可以恢复消息队列。消息系统一般都会采用持久化机制。
ActiveMQ
的消息持久化机制有JDBC
、AMQ
、KahaDB
、和LevelDB
,无论使用哪种持久化方式,消息的存储逻辑都是一致的。
思维导图:
存储逻辑:
就是在发送者将消息发送到MQ服务器后
,消息中心首先将消息持久化到 本地数据文件、内存数据库或者远程库等
,在试图将消息发送给接收者,成功则将消息从存储中删除
,失败则继续尝试发送
。
消息中间件启动以后,首先要检查指定的存储配置,如果有未发送成功的消息,则需要把消息发送出去。
二、持久化方式
1、AMQ message Store(了解)
AMQ使一种文件消息存储,它具有写入消息快的特点。
原理:
- 写入消息时,会
将消息按顺序追加到日志文件
,性能很高。为了提升性能,创建消息主键索引
,并且提供缓存机制
,进一步提升性能。 - 每个
日志文件的大小都是有限制的
(默认32m
,可自行配置),当一个存储文件中的消息已经全部被消费
,那么这个文件将会被表示为可删除,在下一个清除判断,这个文件会被删除
。 - 当超过这个大小,系统会重新建立一个文件。当所有的消息都消费完成,系统会删除这个文件或者归档(取决于配置)。
缺点:
- AMQ Message会
为每一个Destination创建一个索引
,一旦使用了大量的Queue
,索引文件的大小会占用很多磁盘空间
。而且由于索引巨大,一旦Broker崩溃,重建索引的速度会非常慢
。
AMQ使用于5.3之前的版本
,基于文件的存储方式,是以前默认的的消息存储,现在已经不使用了
。
2、KahaDB消息存储(默认)
ActiveMQ从5.4版本开始,推荐使用KahaDB,KahaDB是基于日志文件的
官方文档地址:
原理:
KahaDB的Architecture图:
过程解析:
① 在内存(cache)中的那部分B-Tree是Metadata Cache,通过将索引缓存到内存中,可以加快查询的速度(quick retrival of message data)。但是需要定时将 Metadata Cache 与 Metadata Store同步。
这个同步过程就称为:check point
。由checkpointInterval选项 决定每隔多久时间进行一次checkpoint操作。
② BTree Indexes
则是保存在磁盘上
的,称为Metadata Store,它对应于文件db.data
,它就是对Data Logs以B树的形式 索引
。有了它,Broker(消息服务器)
可以快速地重启恢复,因为它是消息的索引
,根据它就能恢复出每条消息的location
。
如果Metadata Store被损坏,则只能扫描整个Data Logs来重建B树了,这个过程是很复杂且缓慢的。
③ Data Logs
则对应于文件 db-<number>.log
,默认是32MB
,Data Logs以日志形式存储消息,它是生产者生产的数据的真正载体。
④ Redo Log
则对应于文件 db.redo
,redo log
的原理用到了“Double Write”
。
kahadb在消息保存目录中只有4个文件和一个lock,跟ActiveMQ的却文件存储引擎相比这就非常简洁了。
4个文件和一个锁:
db-<number>.log
:KahaDB存储消息到预定大小的数据记录文件中,文件命名为db-<number>.log
。当数据文件已满时,一个新的文件会随之创建。number的数值也会递增,它随着消息数量的增多,如每32M一个文件
,文件名安装数字进行依次编号
。当不再有引用到数据文件中的任何消息时文件会被删除或者归档
。db.data
: 该文件包含了持久化的BTree的索引,索引了消息数据记录中的消息,他是消息索引文件,本质上时B-Tree(B数),使用B-Tree作为索引指向db-.log里面的存储消息。db.redo
: 主要用来进行消息恢复。db.free
:当前db.data文件里面哪些时空闲的,文件具体内容时所有空闲页的IDlock
: 锁文件
KahaDB主要特性:
- 日志形式存储消息;
- 消息索引以B-Tree结构存储,可以快速更新;
- 完全支持JMS事务;
- 支持多种恢复机制;
在配置文件中我们可以看到下面的配置,说明的ActiveMQ默认使用的KahaDB
配置方式:
directory
: 指定持久化消息的存储目录journalMaxFileLength
: 指定保存消息的日志文件大小,具体根据你的实际应用配置
<persistenceAdapter>
<kahaDB directory="${activemq.data}/activemq-data" journalMaxFileLength="16mb"/>
</persistenceAdapter>
说明:
- 目前默认的存储方式,可用于任何场景,提高了性能和恢复能力。
- 消息存储使用一个事务日志和仅仅一个索引文件来存储它的所有地址。
- kahaDB时专门针对消息持久化的解决方案,它对典型的消息使用模式进行了优化。
- 数据被追加到data logs中,当不在需要log文件中的数据时,log文件会被丢弃。