(六)--ActiveMQ的消息存储和持久化

本文深入探讨ActiveMQ的消息持久化机制,包括KahaDB、LevelDB和JDBC存储方案,解析不同存储方式的工作原理、配置及优缺点,帮助理解如何确保MQ服务器故障时消息不丢失。

1. 官网

https://activemq.apache.org/persistence
面试题: MQ的高可用?
(1.事务, 2.持久,3. 签收MQ自带)-可持久化

2. 是什么

说明:
-------为了避免意外宕机以后丢失信息, 需要做到重启后可以恢复消息队列, 消息系统一般都会采用持久化机制
ActiveMQ的消息持久化机制有JDBC,AMQ, KahaBDLevelDB, 无论使用哪种持久化方式, 消息的存储逻辑都是一致的.

就是在发送者将消息发送出去后, 消息中心首先将消息存储到本地数据文件, 内存数据库或者远程数据库 等 再试图将消息发送给接受者,成功则将消息从存储中删除, 失败则继续尝试发送.

消息中心启动以后首先要检查指定的存储位置, 如果有未发送成功的消息,则需要把消息发送出去.
一句话: MQ服务器down机了,消息不会丢失的机制

3. 有哪些

3.1 AMQ Message Store(了解) 5.0版本以前的

基于文件的存储方式, 是以前的默认消息存储, 现在不用了

3.2 KahaDB 消息存储(默认)

1. 基于日志文件, 从ActiveMQ5.4 开始默认的持久化插件 类似于redis的AOF
2. 官网推荐使用KahaDB

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

[root@localhost kahadb]# pwd
/opt/apache-activemq-5.15.11/data/kahadb
[root@localhost kahadb]# ll
总用量 748
-rw-r--r--. 1 root root 33554432 1月   2 14:30 db-1.log
-rw-r--r--. 1 root root   204800 1月   2 15:20 db.data
-rw-r--r--. 1 root root    69760 1月   2 15:20 db.redo
-rw-r--r--. 1 root root        8 1月   2 14:30 lock

3.2.1 KahaDB的存储原理

KahaDB在消息保存目录只有4类文件和一个lock,跟ActiveMQ的其他几种文件存储引擎相比这就非常简洁了.

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

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

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

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

  5. lock文件锁, 表示当前获得KahaDB读写权限的broker

3.3 JDBC消息存储

在这里插入图片描述

3.3.1. MQ + Mysql

在这里插入图片描述

3.3.2. 添加mysql数据库的驱动包到lib文件夹

cp mysql-connector-jar-8.0.18.jar /opt/apache-activemq-5.15.11/lib/

jar包如下:
在这里插入图片描述

3.3.3. jdbcPersistenceAdapter配置

在/conf路径下修改activemq.xml配置文件,按照如下修改

修改前KahaDB

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

修改后jdbcPersistenceAdapter

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

dataSource指定将要引用的持久化数据库的bean名称,createTablesOnStartup是否在启动的时候创建数据表, 默认值是true, 这样每次启动都会创建数据表了,一般是第一次启动的时候创建为true之后改成false

dataSource="#mysql-ds"为数据库引用*
在这里插入图片描述

3.3.4. 建仓SQL和建表说明在这里插入图片描述

1. ACTIVEMQ_MSGS说明:

ID :自增的数据库主键

CONTAINER: 消息的Destination

MSGID_PROD: 消息发送者的主键

MSG_SEQ: 是发送消息的顺序, MSGID_PROD+MSG_SEQ可以组成JMS的MessageID

EXPIRATION: 消息的过期时间, 存储的是从1970-01-01到现在的毫秒数

MSG: 消息本体的Java序列化对象的二进制数据

PRIORITY: 优先级, 从0-9,数值越大优先级越高


消息表,缺省表名为ACTIVEMQ_MSGS, queue和topic都存在里面,


2.ACTIVEMQ_ACKS

activemq_acks用于存储订阅关系,如果是持久化Topic,订阅者和服务器的订阅关系在这个表保存,
数据库字段如下:

CONTAINER: 消息的Destination

SUB_DEST: 如果是使用Static集群, 这个字段会有集群其他系统的信息

CLIENT_ID : 每个订阅者都必须有一个唯一的客户端ID用以区分

SUB_NAME: 订阅者名称

SELECTOR: 选择器,可以选择只消费满足条件的消息, 条件可以用自定义属性实现, 
可支持多属性AND和OR操作

LAST_ACKED_ID: 记录消费过的ID
ACTIVEMQ_ACKS表存储订阅的消息和最后一个持久订阅接收的消息ID

3. ACTIVEMQ_LOCK
表activemq_lockk在集群环境中才有用, 只有一个Broker可以获得消息, 称为Master Broker, 其他的只能作为备份等待Master Broker不可用, 才可能成为下一个Master Broker, 这个表用于记录哪个Broker是当前的Master Broker.

3.3.5. 代码运行验证

一定要开启持久化

messageProducer.setDeliveryMode(Delivery.PERSISTENT);

在这里插入图片描述
在点对点类型中
当DeliveryMode设置为NON_PERSISTENCE时,消息被保存在内存中;
当DeliveryMode设置为PERSISTENCE时,消息保存在broker的相应的文件或者数据库中.

而且点对点类型中消息一旦被Consumer消费就从broker中删除.

小总结 :

如果是queue
在没有消费者消费的情况下会将消息保存到activemq_msgs表中,只要有任意一个消费者已经消费过了,消费之后这些消息将会立即被删除.


在配置关系型数据库作为ActiveMQ的持久化存储方案时, 有坑

数据库jar包
记得需要使用到的相关jar文件配置到ActiveMQ安装路径下的lib目录, mysql-jdbc驱动的jar包和对应的数据库可连接池jar包

createTablesOnStartup属性
在jdbcPersistenceAdapter标签中设置了createTablesOnStartup属性为true时在第一次启动ActiveMQ时, ActiveMQ服务节点会自动创建所需要的数据表,启动完成之后可以去掉这个属性,或者更改createTableOnStartup属性为false

下划线坑爹
“java.lang.IllegalStateException: BeanFactory not initialized or already closed”
这是因为你的操作系统的机器名中有"_"符号,请更改机器名并且重启后即可解决问题.

3.4 LevelDB消息存储(了解)

这种文件系统是从ActiveMQ5.8之后引进的, 它和KahaDB非常相似, 也是基于文件的本地数据库存储形式, 但是它提供比KahaDB更快的持久性.

它提供比KahaDB更快的持久性.

但它不使用自定义B-Tree实现来索引预写日志, 而是使用基于LevelDB的索引

默认配置如下:

<persistenceAdapter>
	<levelDBdirectory="activemq-data"/>
</persistenceAdapter>

如果是topic
一般是先启动消费订阅然后再生产的情况下会将消息保存到activemq_acks.

3.5 JDBC Messagestore wiith ActiveMQ Journal

3.5.1 是什么

高速高性能的缓存日志
说明:
这种方式克服了JDBC Store的不足,JDBC每次消息过来, 都需要去写库和读库.

ActiveMQ Journal, 使用高速缓存写入技术,大大提高了性能.

当消费者的消费速度能够及时跟上生产者的生产速度时, journal文件能够大大减少需要写入到DB中的消息.

举个例子,
生产者生产 了1000条消息,这1000条消息会保存到journal文件,
如果消费这的消费速度很快的情况下,在journal文件还没有同步到DB之前,
消费者已经消费你了90%的以上的消息, 
那么这个时候只需要同步剩余的10%的消息到DB. 


如果消费者的消费速度很慢, 这个时候journal文件可以使消息以批量方式写到DB.

配置
在这里插入图片描述

ActiveMQ持久化机制小总结

持久化消息主要是指:
MQ所在的服务器down了消息不会丢失的机制.

持久化机制演化过程:
从最初的AMQ Message Store方案到ActiveMQ V4版本中退出的High Performance jourmal(高性能事务支持) 附件, 并且同步退出了关于关系型数据库的存储方案.ActiveMQ 5.3版本中又推出了KahaDB的支持(V5.4版本后称为ActiveMQ默认的持久化方案), 后来ActiveMQ V5.8版本开始支持LevelDB,到现在, V5.9+版本提供了标准的Zookeeper+LevelDB集群化方案, 我们重点介绍了KahaDB, LevelDB和mysql数据库者三种持久化存储方案,

ActiveMQ的消息持久化机制有:

AMQ 基于日志文件
KahaDB 基于日志文件 从ActiveMQ5.4开始默认的持久化插件
JDBC 基于第三方数据库
LevelDB 基于文件的本地数据库存储, 从ActiveMQ 5.8版本后又推出了LevelDB的持久化引擎性能高于KahaDB

Replicated LevelDB Store 从ActiveMQQ 5.9 提供了基于LevelDB和Zookeeper的数据复制方式,用于Master-slave方式的首选数据复制方案

无论是哪种持久化方式, 消息的存储逻辑都是一致的.
就是在发送者将消息发送出去后, 消息中心首先将消息存储到本地数据文件, 文件数据库或者远程数据库等, 然后试图将消息发送给接受者,
发送成功则将消息从存储中删除失败则继续尝试. 消息中心启动以后首先要检查指定的存储位置, 如果有未发送成功的消息, 则需要把消息发送出去.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值