ActiveMQ消息持久化

前言

在前面我我们讲JMS规范的时候有简单的说过activeMQ的消息持久化,演示了如何来设置使消息能够持久化存储。

本次呢,我们将来深入了解activeMQ的消息持久化,看看底层的实现机制。

是什么?

官方文档:http://activemq.apache.org/persistence
在这里插入图片描述
此页介绍了activeMQ各个版本的持久化特性。

消息持久化就是为了避免意外宕机以后丢失信息,需要做到重启后可以恢复消息队列,消息系统一般都会采用持久化机制。ActiveMQ的消息持久化机制有AMQ,KahaDB,JDBC和LevelDB,无论使用哪种持久化方式,消息的存储逻辑都是一致的。就是在发送者将消息发送出去后,消息中心首先将消息存储到本地数据文件、内存数据库或者远程数据库等。再试图将消息发给接收者,成功则将消息从存储中删除,失败则继续尝试尝试发送。消息中心启动以后,要先检查指定的存储位置是否有未成功发送的消息,如果有,则会先把存储位置中的消息发出去。

简单理解就是:ActiveMQ宕机了,消息不会丢失的机制。

有哪些?

  • AMQ Mesage Store:它是一种文件存储形式,它具有写入速度快和容易恢复的特点。消息存储再一个个文件中文件的默认大小为32M,当一个文件中的消息已经全部被消费,那么这个文件将被标识为可删除,在下一个清除阶段,这个文件被删除。适用于ActiveMQ5.3之前的版本。是以前的默认消息存储,现在不用了

  • KahaDB:KahaDB是目前默认的存储方式,可用于任何场景,提高了性能和恢复能力。消息存储使用一个事务日志和仅仅用一个索引文件来存储它所有的地址。KahaDB是一个专门针对消息持久化的解决方案,它对典型的消息使用模型进行了优化。数据被追加到data logs中。当不再需要log文件中的数据的时候,log文件会被丢弃。

  • JDBC:基础数据库的消息存储

  • JDBC Journa:是一种日志+数据库的持久化机制,当生产者发送了消息,首先会放到日志中,等过一段时间,如果此消息还未被消费掉,才会将此消息入库。就相当于数据库前加了层redis,它解决了传统JDBC频繁读写所带来性能问题。

  • LevelDB:这种文件系统是从ActiveMQ5.8之后引进的,它和KahaDB非常相似,也是基于文件的本地数据库存储形式,但是它提供比KahaDB更快的持久性。但它不使用自定义B-Tree实现来索引独写日志,而是使用基于LevelDB的索引。

怎么用?

KahaDB

官方介绍:http://activemq.apache.org/kahadb
在这里插入图片描述
activemq.xml配置:

<persistenceAdapter>
    <kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>

还可以加一些其它参数,具体的在此处就不在演示了,可参考官方文档。

如果你的activeMQ是5.4版本或以上版本的,默认就是使用kahaDB方式。

消息的持久化的文件放在activeMQ的安装目录/data/kahadb下:
在这里插入图片描述
kahadb目录文件介绍:kahadb目录下一共有4种文件和一个lock。

  • db-number.log(db-1.log):KahaDB存储消息到预定大小的数据纪录文件中,文件名为db-number.log。当数据文件已满时,一个新的文件会随之创建,number数值也会随之递增,它随着消息数量的增多,如没32M一个文件,文件名按照数字进行编号,如db-1.log,db-2.log······。当不再有引用到数据文件中的任何消息时,文件会被删除或者归档。

  • db.data:该文件包含了持久化的BTree索引,索引了消息数据记录中的消息,它是消息的索引文件,本质上是B-Tree(B树),使用B-Tree作为索引指向db-number。log里面存储消息。

  • db.free:当问当前db.data文件里面哪些页面是空闲的,文件具体内容是所有空闲页的ID

  • db.redo:用来进行消息恢复,如果KahaDB消息存储再强制退出后启动,用于恢复BTree索引。

  • lock:文件锁,表示当前kahadb独写权限的broker。

JDBC

首先我们需要有一个能够与activeMQ服务通信的数据库服务,并新建一个名称为activemq的数据库(也可以是其它名称)。

数据库可以是mysql也可以是Oracle,只不过是配置不同,以下示例将是在mysql上进行的。
在这里插入图片描述
activemq.xml配置:

<!--  
<persistenceAdapter>
     <kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>
-->

<persistenceAdapter>  
      <jdbcPersistenceAdapter dataSource="#mysql-ds"> 
</persistenceAdapter>

<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://数据库地址/activemq?relaxAutoCommit=true"/> 
    <property name="username" value="数据库账号"/> 
    <property name="password" value="数据库密码"/> 
    <property name="poolPreparedStatements" value="true"/> 
 </bean> 

根据自己的环境和个性化需要,可修改数据库的连接池、驱动、数据库地址、数据库账号、密码等配置。

注意数据库连接配置要放到</broker>标签和<import>标签之间:
在这里插入图片描述
接着添加数据库的驱动包到activeMQ的lib目录下:
在这里插入图片描述
默认是的dbcp数据库连接池,如果要换成其他数据库连接池,也需要将该连接池jar包,放到lib目录下。

配置好后,启动activeMQ服务,会自动创建表,可以在jdbcPersistenceAdapter标签中增加createTableOnStartup="false"配置,设置为不自动创建,默认是自动创建的,一般情况下我们会在activeMQ首次启动表创建好之后将配置改为不自动创建。

启动好之后就可以看到创建好的三张表:
在这里插入图片描述
activemq_acks:存储订阅关系,如果是持久化topic,订阅者和服务器的订阅关系会在这个表保存,字段如下:

字段名数据类型描述
CONTAINERvarchar(250)消息的Destination
SUB_DESTvarchar(250)如果是使用static集群,这个字段会存储其它集群的信息
CLIENT_IDvarchar(250)自己定义的订阅者的唯一id
SUB_NAMEvarchar(250)订阅者的名称
SELECTORvarchar(250)选择器,可以选择只消费满足条件的消息。条件可以用自定义属性实现,可支持多属性AND和OR操作
LAST_ACKED_IDbigint(20)最后一次确认ID,这个字段存的该该订阅者最后一次收到的消息的ID
PRIORITYbigint(20)消息优先级

在这里插入图片描述

activemq_lock:在集群环境下使用,用于记录哪个broker是当前的master

字段名数据类型描述
IDbigint(20)主键
TIMEbigint(20)时间
BROKER_NAMEvarchar(250)broker的名称

activemq_msgs:消息表,queue和topic消息都存在此表里面

字段名数据类型描述
IDbigint(20)主键
CONTAINERvarchar(250)消息的Destination
MSGID_PRODvarchar(250)消息id,由activeMQ生成
MSGID_SEQbigint(20)消息顺序
EXPIRATIONbigint(20)消息的过期时间
MSGlongblob消息的二进制数据
PRIORITYbigint(20)消息优先级

在这里插入图片描述
在这里插入图片描述
发送queue消息:

  • 当DeliveryMode设置为NON_PERSISTENCE时,消息被保存在内存中
  • 当DeliveryMode设置为PERSISTENCE时,消息保存在activemq_msgs表中
  • 消息一旦被Consumer消费,就会从activemq_msgs表中删除

发送topic消息:

  • 先启动消费订阅者然后再生产的情况下会将持久订阅者永久保存到activemq_acks
  • 生产者发送的topic消息永久保存在activemq_msgs
  • 在activemq_acks表中的订阅者有一个last_ack_id对应了activemq_msgs中的id字段,这样就知道订阅者最后收到的消息是哪一条。
  • 持久化topic的消息不管是否被消费,是否有消费者,产生的数据永远都存在,且activemq_msgs种只存储一条,消费者消费完后,消息还会保留
JDBC Journa

JDBC Journa是为了解决JDBC Store的不足,JDBC的方式,每次消息过来,都要对数据库进行读写。ActiveMQ Journal,使用高速缓存写入技术,大大提高了性能。当消费者的速度能够及时跟上生产者消息的生产速度时,journal文件能够大大减少需要写入到DB中的消息。

举个例子:生产者生产了1000条消息,这1000条消息会保存到journal文件,如果消费者的消费速度很快的情况下,在journal文件还没有同步到DB之前,消费者已经消费了90%的以上消息,那么这个时候只需要同步剩余的10%的消息到DB。如果消费者的速度很慢,这个时候journal文件可以使消息以批量方式写到DB。
为了高性能,这种方式使用日志文件存储+数据库存储。先将消息持久到日志文件,等待一段时间再将未消费的消息持久到数据库。该方式要比JDBC性能要高。

activemq.xml配置:

<persistenceFactory>        
    <journalPersistenceAdapterFactory 
            journalLogFiles="5" 
            journalLogFileSize="32768" 
            useJournal="true" 
            useQuickJournal="true" 
            dataSource="#mysql-ds" 
            dataDirectory="../activemq-data" /> 
</persistenceFactory>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值