ActiveMQ入门教程(四)之持久化

ActiveMQ中,持久化是指对消息数据的持久化。在ActiveMQ中,默认的消息是保存在内存中。当内存容量不足的时候,或ActiveMQ正常关闭的时候,会将内存中的未处理的消息持久化到磁盘中。具体的持久化策略由配置文件中的具体配置决定。

所有的持久化配置在conf/activemq.xml中配置,配置信息都在broker标签内部定义,ActiveMQ提供了插件式的消息存储,主要由如下几种:

1.KahaDB消息存储-提供了容量的提升和恢复能力,是现在的默认存储方式

2.JDBC消息存储-消息基于JDBC存储的 

3.LevelDB存储

4.Memory消息存储-基于内存的消息存储

1.kahadb方式

KahaDB是默认的持久化策略,所有消息顺序添加到一个日志文件中,同时另外有一个索引文件记录指向这些日志的存储地址,还有一个事务日志用于消息回复操作。是一个专门针对消息持久化的解决方案,它对典型的消息使用模式进行了优化。

在data/kahadb这个目录下,会生成四个文件,来完成消息持久化 


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

那么如何配置kahadb的持久化策略呢?在conf/activemq.xml文件里面添加以下配置,不过这个是默认就在里面的配置。

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

KahaDB的属性件下表格:

属性名称属性值描述
directoryactivemq-data消息文件和日志的存储目录
indexWriteBatchSize1000一批索引的大小,当要更新的索引量到达这个值时,更新到消息文件中
indexCacheSize1000内存中,索引的页大小
enableIndexWriteAsyncfalse索引是否异步写到消息文件中
journalMaxFileLength32mb一个消息文件的大小
enableJournalDiskSyncstrue是否讲非事务的消息同步写入到磁盘
cleanupInterval30000清除操作周期,单位ms
checkpointInterval5000索引写入到消息文件的周期,单位ms
ignoreMissingJournalfilesfalse忽略丢失的消息文件,false,当丢失了消息文件,启动异常
checkForCorruptJournalFilesfalse检查消息文件是否损坏,true,检查发现损坏会尝试修复
checksumJournalFilesfalse产生一个checksum,以便能够检测journal文件是否损坏。
5.4版本之后有效的属性:
archiveDataLogsfalse当为true时,归档的消息文件被移到directoryArchive,而不是直接删除
directoryArchivenull存储被归档的消息文件目录
databaseLockedWaitDelay10000在使用负载时,等待获得文件锁的延迟时间,单位ms
maxAsyncJobs10000同个生产者产生等待写入的异步消息最大量
concurrentStoreAndDispatchTopicsfalse当写入消息的时候,是否转发主题消息
concurrentStoreAndDispatchQueuestrue当写入消息的时候,是否转发队列消息
5.6版本之后有效的属性:
archiveCorruptedIndexfalse是否归档错误的索引

由于在ActiveMQ V5.4+的版本中,KahaDB是默认的持久化存储方案。所以即使你不配置任何的KahaDB参数信息,ActiveMQ也会启动KahaDB。这种情况下,KahaDB文件所在位置是你的ActiveMQ安装路径下的/data/broker.Name/KahaDB子目录。其中broker.Name/KahaDB子目录。其中{broker.Name}代表这个ActiveMQ服务节点的名称。

正式的生产环境还是建议在主配置文件中明确设置KahaDB的工作参数:

 <persistenceAdapter>
    <kahaDB directory="activemq-data"
            journalMaxFileLength="32mb"
            concurrentStoreAndDispatchQueues="false"
            concurrentStoreAndDispatchTopics="false"
            />
  </persistenceAdapter>

2.JDBC持久化方式

从ActiveMQ 4+版本开始,ActiveMQ就支持使用关系型数据库进行持久化存储——通过JDBC实现的数据库连接。可以使用的关系型数据库囊括了目前市面的主流数据库。

使用JDBC的方式持久化我们就得修改之前的配置文件:(注意:createTablesOnStartup="true"每次启动都会创建新表,第二次启动一定要将createTablesOnStartup改为"false",否则会将数据库的数据清理掉)

        <persistenceAdapter>
            <!--<kahaDB directory="${activemq.data}/kahadb"/>-->
			<jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="true"/>
        </persistenceAdapter>

在broker结点外面,增加数据源的配置,如下:


	<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://47.192.5.36:5186/activemq?relaxAutoCommit=true"/>
		<property name="username" value="root"/>
		<property name="password" value="root"/>
		<property name="maxActive" value="200"/>
		<property name="poolPreparedStatements" value="true"/>
	</bean>

具体的activemq.xml

<?xml version='1.0' encoding='utf-8'?>
<!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for additional information regarding copyright ownership.
    The ASF licenses this file to You under the Apache License, Version 2.0
    (the "License"); you may not use this file except in compliance with
    the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<!-- START SNIPPET: example -->
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">

    <!-- Allows us to use system properties as variables in this configuration file -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <value>file:${activemq.conf}/credentials.properties</value>
        </property>
    </bean>

   <!-- Allows accessing the server log -->
    <bean id="logQuery" class="io.fabric8.insight.log.log4j.Log4jLogQuery"
          lazy-init="false" scope="singleton"
          init-method="start" destroy-method="stop">
    </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://47.192.5.36:5186/activemq?relaxAutoCommit=true"/>
		<property name="username" value="root"/>
		<property name="password" value="root"/>
		<property name="maxActive" value="200"/>
		<property name="poolPreparedStatements" value="true"/>
	</bean>
    <!--
        The <broker> element is used to configure the ActiveMQ broker.
    -->
    <broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">

        <destinationPolicy>
            <policyMap>
              <policyEntries>
                <policyEntry topic=">" >
                    <!-- The constantPendingMessageLimitStrategy is used to prevent
                         slow topic consumers to block producers and affect other consumers
                         by limiting the number of messages that are retained
                         For more information, see:

                         http://activemq.apache.org/slow-consumer-handling.html

                    -->
                  <pendingMessageLimitStrategy>
                    <constantPendingMessageLimitStrategy limit="1000"/>
                  </pendingMessageLimitStrategy>
                </policyEntry>
              </policyEntries>
            </policyMap>
        </destinationPolicy>


        <!--
            The managementContext is used to configure how ActiveMQ is exposed in
            JMX. By default, ActiveMQ uses the MBean server that is started by
            the JVM. For more information, see:

            http://activemq.apache.org/jmx.html
        -->
        <managementContext>
            <managementContext createConnector="false"/>
        </managementContext>

        <!--
            Configure message persistence for the broker. The default persistence
            mechanism is the KahaDB store (identified by the kahaDB tag).
            For more information, see:

            http://activemq.apache.org/persistence.html
        -->
        <persistenceAdapter>
            <!--<kahaDB directory="${activemq.data}/kahadb"/>-->
			<jdbcPersistenceAdapter dataSource="#mysql-ds" createTablesOnStartup="true"/>
        </persistenceAdapter>


          <!--
            The systemUsage controls the maximum amount of space the broker will
            use before disabling caching and/or slowing down producers. For more information, see:
            http://activemq.apache.org/producer-flow-control.html
          -->
          <systemUsage>
            <systemUsage>
                <memoryUsage>
                    <memoryUsage percentOfJvmHeap="70" />
                </memoryUsage>
                <storeUsage>
                    <storeUsage limit="100 gb"/>
                </storeUsage>
                <tempUsage>
                    <tempUsage limit="50 gb"/>
                </tempUsage>
            </systemUsage>
        </systemUsage>

        <!--
            The transport connectors expose ActiveMQ over a given protocol to
            clients and other brokers. For more information, see:

            http://activemq.apache.org/configuring-transports.html
        -->
        <transportConnectors>
            <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
            <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
            <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
        </transportConnectors>

        <!-- destroy the spring context on shutdown to stop jetty -->
        <shutdownHooks>
            <bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" />
        </shutdownHooks>


        <!--开启安全认证-->
        <plugins>
        <!--activemq在login.config文件里定义 -->
        <jaasAuthenticationPlugin configuration="activemq"/>
                <authorizationPlugin>
                        <map>
                                <authorizationMap>
                                        <authorizationEntries>
                                               <!-- 表示通配符、所有 admins:表示的是用户组不是用户    read表示读的权限,write表示写的权限,admin表示是否能创建-->
                                                <authorizationEntry queue=">" read="admins" write="admins" admin="admins" />
                                                <authorizationEntry topic=">" read="admins" write="admins" admin="admins" />
                                                <authorizationEntry queue="ActiveMQ.Advisory.>" read="admins" write="admins" admin="admins" />
                                                <authorizationEntry topic="ActiveMQ.Advisory.>" read="admins" write="admins" admin="admins" />
                                       </authorizationEntries>
                                </authorizationMap>
                        </map>
                </authorizationPlugin>
        </plugins>

    </broker>

    <!--
        Enable web consoles, REST and Ajax APIs and demos
        The web consoles requires by default login, you can disable this in the jetty.xml file

        Take a look at ${ACTIVEMQ_HOME}/conf/jetty.xml for more details
    -->
    <import resource="jetty.xml"/>

</beans>
<!-- END SNIPPET: example -->

将mysql的数据库连接包上传到activeMq的lib目录下(注意:mysql版本不一致,mysql-connector-java-xxx的jar包版本不一致,我用的是mysql8版本,所以数据库连接也是用的8版本)

lib下载地址:链接:https://pan.baidu.com/s/1igcYKf4pRhcolCThZMjPNg 
提取码:si6u 

此时,重新启动MQ,就会发现db数据库中多了三张表:activemq_acks,activemq_lock,activemq_msgs,OK,说明activemq已经持久化成功啦!

注意:如果mq日志文件报: Cannot create PoolableConnectionFactory (Could not create connection to database server.)可能的问题是mysql的连接版本(mysql-connector-java-8.0.11.jar)不对,需要替换一下

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

  • container:消息的destination 
  • sub_dest:如果是使用static集群,这个字段会有集群其他系统的信息 
  • client_id:每个订阅者都必须有一个唯一的客户端id用以区分 
  • sub_name:订阅者名称 
  • selector:选择器,可以选择只消费满足条件的消息。条件可以用自定义属性实现,可支持多属性and和or操作 
  • last_acked_id:记录消费过的消息的id


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


activemq_msgs:用于存储消息,Queue和Topic都存储在这个表中。主要的数据库字段如下:

  • id:自增的数据库主键 
  • container:消息的destination 
  • msgid_prod:消息发送者客户端的主键 
  • msg_seq:是发送消息的顺序,msgid_prod+msg_seq可以组成jms的messageid 
  • expiration:消息的过期时间,存储的是从1970-01-01到现在的毫秒数 
  • msg:消息本体的java序列化对象的二进制数据 
  • priority:优先级,从0-9,数值越大优先级越高 
  • activemq_acks用于存储订阅关系。如果是持久化topic,订阅者和服务器的订阅关系在这个表保存。
     

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

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

4.Memory 消息存储
顾名思义,基于内存的消息存储,就是消息存储在内存中。persistent=”false”,表示不设置持 久化存储,直接存储到内存中
在broker标签处设置。

<beans> 
    <broker brokerName="test-broker" persistent="false" xmlns="http://activemq.apache.org/schema/core"> 
    <transportConnectors> 
        <transportConnector uri="tcp://localhost:61635"/> 
    </transportConnectors> 
    </broker>
 </beans>

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值