ActiveMQ 配置jdbc主从
使用 jdbc 方式配置主从模式,持久化消息存放在数据库中。
在同一时刻,只有一个 master broker,master 接受客户端的连接,slave 不接受连接。
当 master 因为关机而下线后,其中一个 slave 会提升为 master,然后接受客户端连接。但原来 master 的非持久消息丢失了,而持久消息保存在数据库中。
broker xml 配置:使用 MySQL 数据源
<!--
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.
-->
<!--
Use JDBC for message persistence
For more information, see: http://activemq.apache.org/persistence.html You need to add Derby database to your classpath in order to make this example work.
Download it from http://db.apache.org/derby/ and put it in the ${ACTIVEMQ_HOME}/lib/optional/ folder
Optionally you can configure any other RDBM as shown below To run ActiveMQ with this configuration add xbean:conf/activemq-jdbc.xml to your command e.g. $ bin/activemq xbean:conf/activemq-jdbc.xml
-->
<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-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd"> <broker useJmx="false" brokerName="jdbcBroker" xmlns="http://activemq.apache.org/schema/core">
<persistenceAdapter>
<jdbcPersistenceAdapter dataDirectory="${activemq.base}/data" dataSource="#mysql-ds"/>
</persistenceAdapter> <transportConnectors>
<transportConnector name="default" uri="tcp://0.0.0.0:61616"/>
</transportConnectors>
</broker> <!-- Embedded Derby DataSource Sample Setup -->
<!-- <bean id="derby-ds" class="org.apache.derby.jdbc.EmbeddedDataSource">
<property name="databaseName" value="derbydb"/>
<property name="createDatabase" value="create"/>
</bean> --> <!-- Postgres DataSource Sample Setup -->
<!--
<bean id="postgres-ds" class="org.postgresql.ds.PGPoolingDataSource">
<property name="serverName" value="localhost"/>
<property name="databaseName" value="activemq"/>
<property name="portNumber" value="0"/>
<property name="user" value="activemq"/>
<property name="password" value="activemq"/>
<property name="dataSourceName" value="postgres"/>
<property name="initialConnections" value="1"/>
<property name="maxConnections" value="10"/>
</bean>
--> <!-- MySql DataSource Sample Setup --> <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.40.8:3306/db_zhang?relaxAutoCommit=true"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<property name="maxActive" value="200"/>
<property name="poolPreparedStatements" value="true"/>
</bean> <!-- Oracle DataSource Sample Setup -->
<!--
<bean id="oracle-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:AMQDB"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
<property name="maxActive" value="200"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
--> </beans>
客户端配置,producer 和 consumer 是一样的:
new ActiveMQConnectionFactory("failover:(tcp://localhost:61616,tcp://localhost:61618)");
以 MySQL 数据库为例,启动 broker 后,MySQL 中会创建 3 张表:
ACTIVEMQ_MSGS 存放持久消息
ACTIVEMQ_LOCK 表中只有一条记录,broker 执行 SELECT * FROM ACTIVEMQ_LOCK FOR UPDATE 获取锁,获得锁的 broker 是 master
ACTIVEMQ_ACKS
broker 获取锁的调用栈如下:

// org.apache.activemq.store.jdbc.DefaultDatabaseLocker
public void doStart() throws Exception { LOG.info("Attempting to acquire the exclusive lock to become the Master broker");
// SELECT * FROM ACTIVEMQ_LOCK FOR UPDATE
String sql = getStatements().getLockCreateStatement();
LOG.debug("Locking Query is "+sql); while (true) {
try {
connection = dataSource.getConnection();
connection.setAutoCommit(false);
lockCreateStatement = connection.prepareStatement(sql);
// 执行 SELECT * FROM ACTIVEMQ_LOCK FOR UPDATE
// 如果成功,则跳出循环。如果超时,则抛异常
lockCreateStatement.execute();
break;
} catch (Exception e) {
try {
if (isStopping()) {
throw new Exception(
"Cannot start broker as being asked to shut down. "
+ "Interrupted attempt to acquire lock: "
+ e, e);
}
if (exceptionHandler != null) {
try {
exceptionHandler.handle(e);
} catch (Throwable handlerException) {
LOG.error( "The exception handler "
+ exceptionHandler.getClass().getCanonicalName()
+ " threw this exception: "
+ handlerException
+ " while trying to handle this exception: "
+ e, handlerException);
} } else {
LOG.debug("Lock failure: "+ e, e);
}
} finally {
// Let's make sure the database connection is properly
// closed when an error occurs so that we're not leaking
// connections
if (null != connection) {
try {
connection.rollback();
} catch (SQLException e1) {
LOG.debug("Caught exception during rollback on connection: " + e1, e1);
}
try {
connection.close();
} catch (SQLException e1) {
LOG.debug("Caught exception while closing connection: " + e1, e1);
} connection = null;
}
}
} finally {
if (null != lockCreateStatement) {
try {
lockCreateStatement.close();
} catch (SQLException e1) {
LOG.debug("Caught while closing statement: " + e1, e1);
}
lockCreateStatement = null;
}
} LOG.info("Failed to acquire lock. Sleeping for " + lockAcquireSleepInterval + " milli(s) before trying again...");
try {
Thread.sleep(lockAcquireSleepInterval);
} catch (InterruptedException ie) {
LOG.warn("Master lock retry sleep interrupted", ie);
}
} LOG.info("Becoming the master on dataSource: " + dataSource);
}
broker 执行 SELECT * FROM ACTIVEMQ_LOCK FOR UPDATE 获取锁,获取成功,则成为 master,如果失败,则睡眠一段时间后,继续获取锁。
超时而抛出的异常:

ActiveMQ 配置jdbc主从的更多相关文章
- AMQ学习笔记 - 14. 实践方案:基于ZooKeeper + ActiveMQ + replicatedLevelDB的主从部署
概述 基于ZooKeeper + ActiveMQ + replicatedLevelDB,在Windows平台的主从部署方案. 主从部署可以提供数据备份.容错[1]的功能,但是不能提供负载均衡的功能 ...
- ActiveMQ配置详解
原文链接 一.消息目的地策略 在节点destinationPolicy配置策略,可以对单个或者所有的主题和队列进行设置,使用流量监控,当消息达到memoryLimit的时候,ActiveMQ会减慢消息 ...
- 从零开始学 Java - Spring 集成 ActiveMQ 配置(一)
你家小区下面有没有快递柜 近两年来,我们收取快递的方式好像变了,变得我们其实并不需要见到快递小哥也能拿到自己的快递了.对,我说的就是类似快递柜.菜鸟驿站这类的代收点的出现,把我们原来快递小哥必须拿着快 ...
- 从零开始学 Java - Spring 集成 ActiveMQ 配置(二)
从上一篇开始说起 上一篇从零开始学 Java - Spring 集成 ActiveMQ 配置(一)文章中讲了我关于消息队列的思考过程,现在这一篇会讲到 ActivMQ 与 Spring 框架的整合配置 ...
- 使用配置文件来配置JDBC连接数据库
1.管理数据库连接的Class 代码如下: package jdbcTest;import java.sql.Connection;import java.sql.DriverManager;impo ...
- spring中配置jdbc数据源
1.加入jdbc驱动器包,mysql-connector-java.jar 2.加入commons-dbcp.jar配置数据源 3.在classpath下新建文件jdbc.properties,配置j ...
- redis主从配置及主从切换 转
redis主从配置及主从切换 转自 http://blog.sina.com.cn/s/blog_67196ddc0101h8v0.html (2014-04-28 17:48:47) 转载▼ 分 ...
- weblogic配置jdbc数据源
weblogic配置jdbc数据源的过程 方法/步骤 启动weblogic 管理服务器,使用管理用户登录weblogic管理控制台 打开管理控制台后,在左侧的树形域结构中,选择服务->数 ...
- 配置mysql主从步骤
在公司开发中,有时候为了缓解数据库压力,会把读写分开为两个数据库来操作,读为一个数据库,写为一个数据库,然后两个数据库做同步,这样能明显降低数据库的压力,下面给大家介绍如何进行mysql主从数据库配置 ...
随机推荐
- ASP.NET —— Web Pages
为简单起见,新建一个空的web工程,再新建一个MVC的视图(.cshtml),因为WP是单页面模型,所以以后就在这个页面中进行试验. Razor语法简介: 变量可用var或者其确切类型声明. 遍历fo ...
- 将实体类、匿名对象转换为SqlParameter列表
/// <summary> /// <remarks> /// <para>将实体类/匿名对象转换为SqlParameter列表</para> /// ...
- shell中的${},##, %% , :- ,:+, ? 的使用
假设我们定义了一个变量为:file=/dir1/dir2/dir3/my.file.txt 可以用${ }分别替换得到不同的值:${file#*/}:删掉第一个/ 及其左边的字符串:dir1/dir2 ...
- C#:导入Excel通用类(Xls格式)
PS:在CSV格式和XLSX格式中有写到通用调用的接口和引用的插件,所以在这个xls格式里面并没有那么详细,只是配上xls通用类. 一.引用插件NPOI.dll.NPOI.OOXML.dll.NPOI ...
- python 部分函数
abs(number) ,返回数字的绝对值cmath.sqrt(number) ,返回平方根,也可以应用于负数float(object) ,把字符串和数字转换为浮点数help() ,提供交互式帮助in ...
- kotlin - 空安全
空安全设计的操作符号 操作符 作用 ? 可空操作符,声明该值可为空 ?. 安全调用操作符 b?.length 如果b非空,就返回b.length,否则返回 null !! 非空断言运算符, ...
- input 输入值的监听 禁止输入特殊字符
1.input 输入值的监听 //用于监听input的值变化(input的值产生变化才会触发事件) (function ($) { $.fn.watch = function (callback) ...
- PCB板的三种敷铜方法解析
1 do not pour over all same net objects:仅仅对相同网络的焊盘进行连接,其他如覆铜.导线不连接. 2 pour over all same net objects ...
- c# 7.0 学习笔记
refer : https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7 out 可以写在里面了 // int result ...
- python实现邮件接口——smtplib模块
1. 思路 使用脚本发送邮件的思路其实和客户端发送邮件一样,过程都是: 登录 —> 写邮件 —> 发送 只不过通过脚本发送时我们需要考虑到整个过程的方方面面.以下为思路导图: 2. Pyt ...