ActiveMq消息持久化
Jms规范的持久化
Jms规范的持久化有两种形式:持久化和非持久化,而对于持久化消息需要存储在稳定的存储介质中,非持久化消息,Jms规定需要尽最大可能进行传送
ActiveMq中的持久化
除了以上两种持久化方式,ActiveMq也支持将消息存储在内存中。
ActiveMq中Queue
和Topic
存储方式由于各自传递消息的方式的不同而有所不用
Queue
对于队列中的消息,是以FIFO的方式进行存储,只有当消息过期或被消费,消息才会从存储介质中消失
Topic
对于持久化的Subscriber来说,订阅者都会有指向Topic中下一条消息的指针,且订阅者获取的消息是消息的一个副本,只有当所有订阅者都获得该消息,才会从存储介质中消失
ActiveMq中的消息存储
KahaDB
KahaDB是ActiveMq从5.4开始默认支持和使用的存储方式,有较好的存储性能和恢复能力(在后面介绍结构会有所提及)。
KahaDB是带有持久化的文件数据库,以追加的方式将消息存入日志文件,类似于redis中aof方式存储数据类似。其消息存储仅仅使用一个事务日志和索引文件
只需要在activemq.conf目录下配置persistenceAdapter
其中的配置属性:
属性名 | 值 | 说明 |
---|---|---|
directory | {activem.data}/data | 存储路径 |
indexWriteBatchSize | 1000 | 一批处理的方式写入磁盘的索引页数 |
indexCacheSize | 10000 | 缓存在内存中的索引页数 |
enableIndexWriteAsync | false | 是否开启异步写入索引 |
journalMaxFileLength | 32mb | 每个消息数据日志存储的最大长度 |
enableJournalDiskSyncs | true | 是否确保每次写入非事务性日志同步地写入磁盘 |
checkpointInterval | 5000 | 检查点设置的时间间隔 |
cleanupInterval | 30000 | 清楚不在使用消息的时间间隔 |
maxAsyncJobs | 10000 | 最大等待存储的消息数 |
KahaDB存储结构
Cache:不是所用生产者发送的持久化消息都会被存储在磁盘文件中,如果发送的消息被立即需要,则会被暂时存储在内存中
Data Logs:用于真正的存储消息及命令的日志文件,其文件长度由配置文件设定,当超过设定的文件长度,就会创建新的日志文件;每条消息是以追加的方式加入到日志文件中,如果消息不在被需要,则会被移除或者被归档
BtreeIndex:B树索引用于保存data log
中通过消息id进行索引的消息的引用,即保存能指向消息引用的索引
redo log:用于强制关闭ActiveMq时,对B树索引进行恢复,用于容灾备份
KahaDB的存储文件
db-{number}.log:上部分中对data logs
的物理实现,其中archive
即归档,用于保留在使用消息日志的目录,当然只有当归档被设置为可用的时候才会启用
db.data:保存B树索引的文件,是btreeindex的物理实现
db.redo:上部分中对redo log
的物理实现
除此之外:
还有db.free文件:用于保存data.log
中空闲页的id,lock:文件锁,保存获取kahadb读写权限的代理对象(broker)
Jdbc消息存储
通过配置第三方关系数据库进行消息存储
配置方面:
其中需要额外的配置是:createTableOnStartup="false"
,设置启动是否创建表,第一次启动的时候设置为true,后续的启动需要更改为true,不让会重新创建表
在mysql数据库中创建activemq数据库
当activemq创建的时候就会自动创建相应的表
activemq_msgs:消息表
activemq_acks:订阅表(用于Topic)
activemq_lock:集群环境下使用,用于记录那个Borker是主节点
ActiveMq中延时投递和定时投递
属性 | 单位 | 说明 |
---|---|---|
AMQ_SCHEDULED_DELAY | long | 等待投递的时间 |
AMQ_SCHEDULED_PREIOD | long | 定时投递的时间 |
AMQ_SCHEDULED_REPEAT | int | 重复投递的次数 |
AMQ_SCHEDULED_CRON | String | linux中配置cron |
代码地址:https://gitee.com/studycsw/pure-java
其中需要注意的是:
repeat:指的是一条消息的重复次数,所以总的发送消息数第一条发送的消息+重复次数
,即这里的10条
delay:这里指定的是消息发送的延迟时间,即等待一段时间将消息发送到Destination(Topic/Queue),实际上在Queue
中,消息按照FIFO原则被消费,因此队列中一条消息真正交付取决于队列中前置消息的数量,所以Delay设定的是多少秒后消息被发送到Destination
cron:linux系统中调度程序,表达式说明如下:
消息重发和死信队列
消息重发的时机
1. client用了transactions且在session中调用了rollback()
2. client用了transactions且在调用commit()之前关闭或者没有commit()
3. client在 CLIENT_ACKNOWLEDGE的传递模式下,在session中调用了recover()
以上都是对于消费者,默认的重发次数是6次,而超过重发次数之后,ActiveMq就会将消息标记为poison,并放入死信队列
重发三次后:
死信队列
用于存储过期消息及超过重发次数的消息
死信队列的配置
不会将过期或者非持久的消息保存在死信队列,即直接删除。
由于是配置各自的死信队列,即individualDeadLetterStrategy
,则需要指定队列的前缀queuePrifex
或者topicPrifex
useQueueForQueueMessage="true"
是否使用Queue的方式来充当QueueMessage的死信队列
processExpired=false
是否保存过期消息
processNonPersistent=false
是否保存非持久化消息
queue
设置队列名称
站在巨人的肩膀上
《ActiveMq in Action》
ActiveMq官网