activeMQ中对于投递模式设置为持久化的消息,broker接收到到消息之后,会先把消息存储到存储介质,然后再转发到消息的监听者,activeMQ提供以下几种消息持久化策略。
KahaDB存储
KahaDB是默认的持久化策略,所有消息顺序添加到一个日志文件中,同时另外有一个索引文件记录指向这些日志的存储地址,还有一个事务日志用于消息回复操作。是一个专门针对消息持久化的解决方案,它对典型的消息使用模式进行了优化。
在data/kahadb这个目录下,会生成四个文件,来完成消息持久化
1.db.data 它是消息的索引文件,本质上是B-Tree(B树),使用B-Tree作为索引指向db-*.log里面存储的消息
2.db.redo 用来进行消息恢复
3. db-*.log 存储消息内容。新的数据以APPEND的方式追加到日志文件末尾。属于顺序写入,因此消息存储是比较 快的。默认是32M,达到阀值会自动递增
4.lock文件 锁,写入当前获得kahadb读写权限的broker ,用于在集群环境下的竞争处理
那么如何配置kahadb的持久化策略呢?在conf/activemq.xml文件里面添加以下配置,不过这个是默认就在里面的配置。
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
persistenceAdapter>
JDBC存储
使用JDBC持久化方式,数据库默认会创建3个表,每个表的作用如下:
activemq_msgs:queue和topic的消息都存在这个表中
activemq_acks:存储持久订阅的信息和最后一个持久订阅接收的消息ID
activemq_lock:跟kahadb的lock文件类似,确保数据库在某一时刻只有一个broker在访问
那么如何进行配置呢?
首先需要定义一个数据库连接源,我们使用mysql,定义如下:
id="mysqlDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.0.15:3306/activemq?relaxAutoCommit=true"/>
<property name="username" value="test"/>
<property name="password" value="123456"/>
然后使用这个数据源配置持久化策略
<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="mysqlDataSource" createTablesOnStartup="true" />
persistenceAdapter>
同时还必须要将以下三个数据库相关的包放入activemq解压目录下的lib:
commons-dbcp-1.4
mysql-connector-java-8.0.9
commons-pool-1.6
版本的话应该没有限制
配置完成之后重启activemq,可以看到自动创建了三个表:
尝试发送一条持久化消息,查看activemq_msgs表,新增一条记录:
LevelDB存储
LevelDB持久化性能高于KahaDB,虽然目前默认的持久化方式仍然是KahaDB。并且,在ActiveMQ 5.9版本提供 了基于LevelDB和Zookeeper的数据复制方式,用于Master-slave方式的首选数据复制方案。 但是在ActiveMQ官网对LevelDB的表述:LevelDB官方建议使用以及不再支持,推荐使用的是KahaDB
配置方式如下
<persistenceAdapter>
<levelDBdirectory="activemq-data"/>
persistenceAdapter>
Memory 消息存储
顾名思义,基于内存的消息存储,就是消息存储在内存中。persistent=”false”,表示不设置持 久化存储,直接存储到内存中
在broker标签处设置。
<beans>
<broker brokerName="test-broker" persistent="false" xmlns="http://activemq.apache.org/schema/core">
<transportConnectors>
<transportConnector uri="tcp://localhost:61635"/>
transportConnectors>
broker>
beans>
JDBC Message store with ActiveMQ Journal
这种方式克服了JDBC Store的不足,JDBC存储每次消息过来,都需要去写库和读库。 ActiveMQ Journal,使用延迟存储数据到数据库,当消息来到时先缓存到文件中,延迟后才写到数据库中。
当消费者的消费速度能够及时跟上生产者消息的生产速度时,journal文件能够大大减少需要写入到DB中的消息。 举个例子,生产者生产了1000条消息,这1000条消息会保存到journal文件,如果消费者的消费速度很快的情况 下,在journal文件还没有同步到DB之前,消费者已经消费了90%的以上的消息,那么这个时候只需要同步剩余的 10%的消息到DB。 如果消费者的消费速度很慢,这个时候journal文件可以使消息以批量方式写到DB。
配置方式,先把原来的jdbc持久化配置去掉,加入以下配置
<persistenceFactory>
<journalPersistenceAdapterFactory dataSource="#mysqlDataSource" dataDirectory="activemqdata"/>
persistenceFactory>