ActiveMQ 的消息持久化策略
消息持久化对于可靠消息传递来说是一种比较好的方法,即使发送者和接受者不是同时在线,或者消息中心在发送者发送消息后宕机了,消息中心重启后仍然可以将消息发送出去。
消息持久性的原理很简单,就是在发送消息出去后,消息中心首先将消息存储在本地文件、内存或者远程数据库,然后把消息发送给接受者,发送成功后再把消息从存储中删除,失败则继续尝试。
消息中心启动以后首先要检查指定的存储位置,如果有未发送成功的消息,则需要把消息发送出去。
ActiveMQ 的消息持久化机制有 KahaDB,AMQ,JDBC 和 LevelDB,无论使用哪种持久化方式,消息的存储逻辑都是一致的。为了避免意外宕机以后丢失信息,需要做到重启后可以恢复消息队列,消息系统一般都会采用持久化机制。
1、JDBC持久化方式
使用 JDBC 持久化方式,数据库会创建3个表:activemq_msgs,activemq_acks 和 activemq_lock。activemq_msgs 用于存储消息,Queue和Topic都存储在这个表 activemq_acks 用于存储订阅关系,如果是持久化Topic,订阅者和服务器的订阅关系在这个表保存 activemq_lock 用于做集群的时候,实现master选举的表,这个表用于记录哪个 Broker 是当前的 Master Broker
配置方式
1、修改安装目录下conf/acticvemq.xml文件,首先定义一个 mysql-ds 的 MySQL 数据源
<bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/activemq?relaxAutoCommit=true" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
2、然后在 broker 节点下的 persistenceAdapter 节点中配置 jdbcPersistenceAdapter 并且引用刚才定义的数据源
<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="false" />
</persistenceAdapter>
dataSource 指定持久化数据库的bean,createTablesOnStartup 表示是否在启动的时候创建数据表,默认值是true,这样每次启动都会去创建数据表了,因此第一次启动的时候设置为 true,之后改成 false。
3、添加 Jar 包依赖,拷贝到安装目录下的 lib 文件夹下:
JDBC持久化方式一般不使用,了解即可。
2、AMQ 方式
AMQ 基于文件的存储方式,写入速度很快,容易恢复。性能高于 JDBC,写入消息时,会将消息写入日志文件。
为了提升性能,创建消息主键索引,并且提供缓存机制,进一步提升性能。每个日志文件的大小都是有限制的(默认32M,可自行配置)。当超过这个大小,系统会重新建立一个文件。当所有的消息都消费完成,系统会删除这个文件或者归档(取决于配置)。
主要的缺点是 AMQ Message 会为每一个 Destination 创建一个索引,如果使用了大量的 Queue,索引文件的大小会占用很多磁盘空间。而且由于索引巨大,一旦Broker崩溃,重建索引的速度会非常慢。
配置如下
<persistenceAdapter>
<amqPersistenceAdapter directory="${activemq.data}/activemq-data" maxFileLength="32mb"/>
</persistenceAdapter>
3、KahaDB 方式
KahaDB 是从 ActiveMQ 5.4 开始默认的持久化插件,也是项目中默认的持久化存储方式,可用于任何场景,提高了性能和恢复能力。KahaDb 恢复时间远远小于其前身AMQ并且使用更少的数据文件,所以可以完全代替AMQ。
kahaDB 的持久化机制同样是基于日志文件,索引和缓存。消息存储使用一个事务日志和仅仅用一个索引文件来存储它所有的地址。
KahaDB 是一个专门针对消息持久化的解决方案,它对典型的消息使用模式进行了优化,在 KahaDB 中,数据被追加到 data logs中。当不再需要log文件中的数据的时候,log文件会被丢弃。
KahaDB的配置方式
<persistenceAdapter>
<kahaDB directory="${activemq.data}/activemq-data" />
</persistenceAdapter>
KahaDB的存储原理
在安装目录下的 data/kahadb 这个目录下,会生成四个文件db.data 它是消息的索引文件,本质上是 B-Tree(B树),使用 B-Tree 作为索引指向 db-.log 里面存储的消息;db.redo 用来进行消息恢复;db-.log 存储消息内容。新的数据以 APPEND 的方式追加到日志文件末尾。属于顺序写入,因此消息存储是比较快的。默认是32M,达到阀值会自动递增;lock 文件锁,表示当前获得 kahadb 读写权限的 broker;
4、基于内存的消息存储
基于内存的消息存储,主要是存储所有的持久化的消息到内存中。persistent=”false”,表示不设置持久化存储,直接存储到内存中。
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" persistent="false">
ActiveMQ 的消息持久化策略,推荐使用 KahaDB。