ActiveMQ消息持久化
1.消息持久化说明
为了避免意外宕机以后丢失信息,需要做到重启后可以恢复消息队列,消息系统一般都会采用持久化机制
ActiveMQ的消息持久化机制有JDBC、AMQ、KahaDB和LevelDB,无论使用哪种持久化方式,消息的存储逻辑都是一致的
就是在发送者将消息发送出去后,消息中心首先将消息存储到本地数据文件、内存数据库或者远程数据库等再试图将消息发送给接收者,成功则将消息从存储中删除,失败则继续尝试发送
消息中心启动以后首先要检查指定的存储位置,如果有未发送成功的消息,则需要把消息发送出去
2.消息持久化存储方式
1)AMQ Message Store
基于文件的存储方式,是以前的默认消息存储,现在不用了
AMQ是一种文件存储形式,它具有写入速度快和容易恢复的特点。消息存储在一个个文件中,文件的默认大小为32M,当一个存储文件中的消息已经全部被消费了,那么这个文件
将被标识为可删除,在下一个清除阶段,这个文件被删除。AMQ适用于ActiveMQ5.3之前的版本
2)KahaDB消息存储
这个是默认的消息存储,基于日志文件,从ActiveMQ5.4开始默认的持久化插件


KahaDB是目前默认的存储方式,可用于任何场景,提高了性能和恢复能力
消息存储使用一个事务日志和仅仅用一个索引文件来存储它所有的地址
KahaDB是一个专门针对消息持久化的解决方案,它对典型的消息使用模式进行了优化
数据被追加到data logs中,当不再需要log文件中的数据的时候,log文件会被丢弃
KahaDB在消息保存目录中只有4类文件和一个lock
db-<number>.log:存储消息到预定义大小的数据记录文件中,文件名为db-<number>.log,当数据文件已满时,一个新的文件
会随之创建,number数值也会随之递增,它随着消息数量的增多,如每32M一个文件,文件名按照数字进行
编号,如db-1.log,db-2.log...当不再有引用到数据文件的任何消息时,文件会被删除或归档
db.data:该文件包含了持久化的BTree索引,索引了消息数据记录中的消息,它是消息的索引文件,使用B-Tree作为索引指向db-<number>.log里面存储的消息
db.free:当前db.data文件里哪些页面是空闲的,文件具体内容是所有空闲页的ID
db.redo:用来进行消息恢复,如果KahaDB消息存储在强制退出后启动,用于恢复BTree索引
lock:文件锁,表示当前获取KahaDB读写权限的broker
3)JDBC消息存储
mysql数据库
添加mysql数据库的驱动包到lib文件夹

jdbcPersistenceAdapter配置
<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="true">
</persistenceAdapter>
#createTablesOnStartup是否在启动时创建数据表,默认值是true,这样每次启动都会去创建数据表,一般第一次启动的设置为true,之后改成false
数据库连接池配置
<bean id="mysql-ds" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/activemq?relaxAutoCommit=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
将这段代码插入如下图红色标注的位置

建仓SQL和建表说明
创建一个名为activemq的数据库
三张表的说明
ACTIVEMQ_MSGS:消息表,queue和topic都存在里面
| 字段 | 类型 | 说明 |
| ID | INTEGER | 自增数据库主键 |
| CONTAINER | VARCHAR(250) | 消息的Destination |
| MSGID_PROD | VARCHAR(250) | 消息发送者的主键 |
| MSG_SEQ | INTEGER | 是发送消息的顺序,MSGID_PROD+MSG_SEQ可以组成JMS的MessageID |
| EXPIRATION | BIGINT | 消息的过期时间,存储的是从1970-01-01到现在的毫秒数 |
| MSG | BLOB | 消息本体的java序列化对象的二进制数据 |
| PRIORITY | INTEGER | 优先级,从0-9,数值越大优先级越高 |
ACTIVEMQ_ACKS:表存储持久订阅的信息和最后一个持久订阅接收的消息ID
用于存储订阅关系,如果是持久化topic,订阅者和服务器的订阅关系在这个表保存
| 字段 | 类型 | 说明 |
| CONTAINER | VARCHAR(250) | 消息的Destination |
| SUB_DEST | VARCHAR(250) | 如果是使用Static集群,这个字段会有集群其他系统的信息 |
| CLIENT_ID | VARCHAR(250) | 每个订阅者都必须有一个唯一的客户端ID用以区分 |
| SUB_NAME | VARCHAR(250) | 订阅者名称 |
| SELECTOR | VARCHAR(250) | 选择器,可以选择只消费满足条件的消息。条件可以自定义属性实现,可支持多属性AND和OR操作 |
| LAST_ACKED_ID | INTEGER | 记录消费过的消息ID |
ACTIVEMQ_LOCK:在集群环境中才有,只有一个Broker可以获得消息,称为master broker,其他的只能作为备份等的master broker不可用,才
可能成为下一个master broker。这个表用于记录哪个broker是当前的master broker
| 字段 | 类型 | 说明 |
| ID | INTEGER | 自增数据库主键 |
| BROKER_NAME | VARCHAR(250) | 具有锁的activemq代理的名称: |
代码运行验证
代码里要开启持久化
messageProducer.setDeliveryMode(DeliveryMode.PERSISTENT);

数据库情况
运行成功生产的代码
队列(ACTIVEMQ_MSGS)

发布订阅
(ACTIVEMQ_ACKS)

(ACTIVEMQ_MSGS)

运行成功消费者代码
队列(ACTIVEMQ_MSGS)

小总结
队列
当DeliveryMode设置为NON_PERSISTENT时,消息被保存在内存中
当DeliveryMode设置为PERSISTENT时,消息保存在broker的相应的文件或者数据库中
而且点对点类型中消息一旦被消费者消费,就从broker中删除
发布订阅
一般是先启动消费者订阅,然后生产再发送的情况下,会将消息保存到ACTIVEMQ_ACKS表
报错"java.lang.IllegalStateException:BeanFactory not initialized or already closed":操作系统的机器名中有"_"符号 ,更改机器名并且重启即可解决
4)LevelDB消息存储
这个文件系统是从ActiveMQ5.8之后引进的,它和KahaDB非常相似,也是基于文件的本地数据库储存形式,但是它提供比KahaDB更快的持久性
但它不使用自定义B-Tree实现来索引预写日志,而是使用基于LevelDB的索引
<persistenceAdapter>
<levelDBdirectory="activemq-data">
</persistenceAdapter>
5)JDBC Message store with ActiveMQ Journal
这种方式克服了JDBC Store的不足,JDBC 每次消息过来,都需要去写库和读库
ActiveMQ Journal,使用了高速缓存写入技术,大大提高了性能
当消费者的消费速度能够及时跟上生产者消息的生产速度,journal文件能够大大减少需要写入到DB中的消息
举个栗子:
生产者生产了1000条消息,这1000条消息会保存在journal文件,如果消费者的消费速度很快的情况下,在
journal文件还没有同步到DB之前,消费者已经消费了90%以上的消息,那么这个时候只需要同步剩余的10%
的消息到DB,如果消费者消费速度慢,这时journal文件可以使消息以批量方式写到DB
<persistenceFactory> <journalPersistenceAdapterFactory journalLogFiles="4"
journalLogFileSize="32768"
useJournal="true"
useQuickJournal="true" dataSource="#mysql-ds" dataDirectory="activemq-data" /> </persistenceFactory>
浙公网安备 33010602011771号