持久化消息和非持久化消息的存储原理

正常情况下,非持久化消息是存储在内存中的,持久化消息是存储在文件中的。能够存储的最大消息数据在
${ActiveMQ_HOME}/conf/activemq.xml文件中的systemUsage节点 ,SystemUsage配置设置了一些系统内存和硬盘容量

<systemUsage>
<systemUsage>
<memoryUsage>
//该子标记设置整个ActiveMQ节点的“可用内存限制”。这个值不能超过ActiveMQ本身设置的最大内存大小。其中的
percentOfJvmHeap属性表示百分比。占用70%的堆内存
<memoryUsage percentOfJvmHeap="70" />
</memoryUsage>
<storeUsage>
//该标记设置整个ActiveMQ节点,用于存储“持久化消息”的“可用磁盘空间”。该子标记的limit属性必须要进行设置
<storeUsage limit="100 gb" />
</storeUsage>
<tempUsage>
//一旦ActiveMQ服务节点存储的消息达到了memoryUsage的限制,非持久化消息就会被转储到 temp store区域,虽然
我们说过非持久化消息不进行持久化存储,但是ActiveMQ为了防止“数据洪峰”出现时非持久化消息大量堆积致使内存耗
尽的情况出现,还是会将非持久化消息写入到磁盘的临时区域——temp store。这个子标记就是为了设置这个temp
store区域的“可用磁盘空间限制”
<tempUsage limit="50 gb" />
</tempUsage>
</systemUsage>
</systemUsage>

  

Ø 从上面的配置我们需要get到一个结论,当非持久化消息堆积到一定程度的时候,也就是内存超过指定的设置阀值时,ActiveMQ会将内存中的非持久化消息写入到临时文件,以便腾出内存。但是它和持久化消息的区别是,重启之后,持久化消息会从文件中恢复,非持久化的临时文件会直接删除。

消息的持久化策略分析

消息持久性对于可靠消息传递来说是一种比较好的方法,即时发送者和接受者不是同时在线或者消息中心在发送者发送消息后宕机了,在消息中心重启后仍然可以将消息发送出去。消息持久性的原理很简单,就是在发送消息出去
后,消息中心首先将消息存储在本地文件、内存或者远程数据库,然后把消息发送给接受者,发送成功后再把消息从存储中删除,失败则继续尝试。接下来我们来了解一下消息在broker上的持久化存储实现方式

持久化存储支持类型

ActiveMQ支持多种不同的持久化方式,主要有以下几种,不过,无论使用哪种持久化方式,消息的存储逻辑都是一致的。
Ø KahaDB存储(默认存储方式)
Ø JDBC存储
Ø Memory存储
Ø LevelDB存储
Ø JDBC With ActiveMQ Journal

KahaDB存储

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

KahaDB的配置方式

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

KahaDB的存储原理

在data/kahadb这个目录下,会生成四个文件
Ø db.data 它是消息的索引文件,本质上是B-Tree(B树),使用B-Tree作为索引指向db-*.log里面存储的消息
Ø db.redo 用来进行消息恢复
Ø db-*.log 存储消息内容。新的数据以APPEND的方式追加到日志文件末尾。属于顺序写入,因此消息存储是比较
快的。默认是32M,达到阀值会自动递增
Ø lock文件 锁,表示当前获得kahadb读写权限的broker

JDBC存储

使用JDBC持久化方式,数据库会创建3个表:activemq_msgs,activemq_acks和activemq_lock。
ACTIVEMQ_MSGS 消息表,queue和topic都存在这个表中
ACTIVEMQ_ACKS 存储持久订阅的信息和最后一个持久订阅接收的消息ID
ACTIVEMQ_LOCKS 锁表,用来确保某一时刻,只能有一个ActiveMQ broker实例来访问数据库

JDBC存储实践

<persistenceAdapter>
<jdbcPersistenceAdapter dataSource="# MySQL-DS " createTablesOnStartup="true" />
</persistenceAdapter>

  

ataSource指定持久化数据库的bean,createTablesOnStartup是否在启动的时候创建数据表,默认值是true,这样每次启动都会去创建数据表了,一般是第一次启动的时候设置为true,之后改成false

Mysql持久化Bean配置

<bean id="Mysql-DS" 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.11.156:3306/activemq?
relaxAutoCommit=true" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>

  添加Jar包依赖

LevelDB存储

LevelDB持久化性能高于KahaDB,虽然目前默认的持久化方式仍然是KahaDB。并且,在ActiveMQ 5.9版本提供了基于LevelDB和Zookeeper的数据复制方式,用于Master-slave方式的首选数据复制方案。不过,据ActiveMQ官网对LevelDB的表述:LevelDB官方建议使用以及不再支持,推荐使用的是KahaDB。

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

Memory 消息存储:

  基于内存的消息存储,内存消息存储主要是存储所有的持久化的消息在内存中。persistent=”false”,表示不设置持久化存储,直接存储到内存中。

<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。
Ø 将原来的标签注释掉
Ø 添加如下标签

<persistenceFactory>
<journalPersistenceAdapterFactory dataSource="#Mysql-DS" dataDirectory="activemqdata"/>
</persistenceFactory>

Ø 在服务端循环发送消息。可以看到数据是延迟同步到数据库的

ActiveMQ(3)---ActiveMQ原理分析之消息持久化的更多相关文章

  1. ActiveMQ(2)---ActiveMQ原理分析之消息发送

    持久化消息和非持久化消息的发送策略 消息同步发送和异步发送 ActiveMQ支持同步.异步两种发送模式将消息发送到broker上.同步发送过程中,发送者发送一条消息会阻塞直到broker反馈一个确认消 ...

  2. ActiveMQ学习系列(四)----消息持久化到mysql

    前记:目前学习还比较杂乱,还未找到系统化地学习ActiveMq的方法.在网上看到消息持久化的demo,了解了一下,在此记录. 一.目前ActiveMq支持的持久化方法 url:http://activ ...

  3. ActiveMQ(4)---ActiveMQ原理分析之消息消费

    消费端消费消息的原理 我们通过上一节课的讲解,知道有两种方法可以接收消息,一种是使用同步阻塞的MessageConsumer#receive方法.另一种是使用消息监听器MessageListener. ...

  4. 消息队列NetMQ 原理分析1-Context和ZObject

    前言 介绍 NetMQ是ZeroMQ的C#移植版本,它是对标准socket接口的扩展.它提供了一种异步消息队列,多消息模式,消息过滤(订阅),对多种传输协议的无缝访问. 当前有2个版本正在维护,版本3 ...

  5. 消息队列NetMQ 原理分析2-IO线程和完成端口

    消息队列NetMQ 原理分析2-IO线程和完成端口 前言 介绍 目的 IO线程 初始化IO线程 Proactor 启动Procator线程轮询 处理socket 获取超时时间 从完成端口获取处理完的状 ...

  6. 消息队列NetMQ 原理分析3-命令产生/处理和回收线程

    消息队列NetMQ 原理分析3-命令产生/处理和回收线程 前言 介绍 目的 命令 命令结构 命令产生 命令处理 创建Socket(SocketBase) 创建连接 创建绑定 回收线程 释放Socket ...

  7. 消息队列NetMQ 原理分析4-Socket、Session、Option和Pipe

    消息队列NetMQ 原理分析4-Socket.Session.Option和Pipe 前言 介绍 目的 Socket 接口实现 内部结构 Session Option Pipe YPipe Msg Y ...

  8. 消息队列NetMQ 原理分析5-StreamEngine、Encord和Decord

    消息队列NetMQ 原理分析5-StreamEngine,Encord和Decord 前言 介绍 目的 StreamEngine 发送数据 接收数据 流程分析 Encoder V2Encoder V1 ...

  9. 消息中间件-activemq实战之消息持久化(六)

    对于activemq消息的持久化我们在第二节的时候就简单介绍过,今天我们详细的来分析一下activemq的持久化过程以及持久化插件.在生产环境中为确保消息的可靠性,我们肯定的面临持久化消息的问题,今天 ...

随机推荐

  1. javascript 创建节点和新增节点

    createElement(tabName) 创建一个为tagName的新元素节点 ANode.appendChild(BNode)把B节点追加至A节点的末尾 insertBefore(ANode,B ...

  2. Hot Chocolate 一个.net 平台的graphql 框架

    在看昨天发布的新版技术雷达中,看到了一个.net 的graphql 框架Hot Chocolate 还是比较激动,尽管好久不搞 .net 了,但是这个框架还是值得看看的,后边学习下 参考资料 http ...

  3. 测试CentOS-7-x86_64-Minimal-1708.iso这种光盘安装效果

    在dvd1光盘安装选择mininal时有292个包 [root@localhost ~]# rpm -qa|wc -l 292 [root@localhost ~]# 测试下使用mininal的iso ...

  4. 我提出了一个 Lean Html 5 的 概念 和 标准

    提出 Lean Html 5 是因为 Html 可以作为 一个 应用程序 开发 的 标准 和 平台, 应用程序 包括 Web 程序 , 本地程序 , 桌面程序 , 嵌入式程序 , 串口通信 等 . L ...

  5. C# 每个字节接受 处理串口数据 的方法

      /// <summary> /// 向串口发送信息,有返回值 /// </summary> /// <param name="serialPort" ...

  6. redux源码解读(二)

    之前,已经写过一篇redux源码解读(一),主要分析了 redux 的核心思想,并用100多行代码实现一个简单的 redux .但是,那个实现还不具备合并 reducer 和添加 middleware ...

  7. cmd常用命令总结

    1.cmd不同盘符之间切换 方法(1): cd /d 路径如:cd /d c:/windows 方法(2): d:2.cls 清空cmd窗口dir 查看文件夹下的目录md 创建文件夹rd 删除文件夹c ...

  8. JavaScript 集合对象

    1. 集合对象 1.1 Object 关于Object类型的创建和底层存储原理我在另一篇文章有说明: JavaScript 对象属性底层原理 我们知道了大多数情况下Object底层都是Hash结构,我 ...

  9. Some elementary algorithms on discrete differential geometry(DDGSpring2016 Demos)

    I studied the on-line course(http://brickisland.net/DDGSpring2016/) by myself, and here are the scre ...

  10. cmake中添加-fPIC编译选项方法

    合并openjpeg/soxr/vidstab/snappy等多个cmake库时,为了解决下述问题: relocation R_X86_64_32 against `.text' can not be ...