ActiveMQ 事务和XA
1. 客户端怎样显式地使用事务?
producer 开启事务(代码片段):
ActiveMQSession session = (ActiveMQSession)connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("TEST.FOO");
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.PERSISTENT); // 开启事务
// 发送 TransactionInfo 消息 BEGIN
session.getTransactionContext().begin(); for (int i = 0; i < 2; i++) {
// Create a message
String text = "zhang";
TextMessage message = session.createTextMessage(text);
producer.send(message);
}
// session.getTransactionContext().rollback();
//提交事务
// 发送 TransactionInfo 消息 COMMIT_ONE_PHASE
session.getTransactionContext().commit();
2. broker 处理事务的入口:
TransportConnection.processBeginTransaction
TransportConnection.processCommitTransactionOnePhase
TransportConnection.processCommitTransactionTwoPhase
broker 处理事务的逻辑在 TransactionBroker 类中。
那么,具体在 Queue 中是怎样体现事务的呢?
ActiveMQ 客户端默认不会开启事务,而如果客户端显式地开启了事务,则 Queue 中可能会存在多个事务,一个事务中必然会有一个消息列表,当客户端提交事务时,Queue 接收事务对应的消息列表,而如果客户端回滚事务,则 Queue 会删除这些消息。
Queue 中的事务变量:
// 键是Transaction,值是对应的消息列表
final ConcurrentHashMap<Transaction, SendSync> sendSyncs = new ConcurrentHashMap<Transaction, SendSync>();
private final LinkedList<Transaction> orderIndexUpdates = new LinkedList<Transaction>();
Queue 内部类 SendSync 封装了消息和同步操作:
class SendSync extends Synchronization {
class MessageContext {
public Message message;
public ConnectionContext context;
public MessageContext(ConnectionContext context, Message message) {
this.context = context;
this.message = message;
}
}
final Transaction transaction;
// 这就是我要找的消息列表
List<MessageContext> additions = new ArrayList<MessageContext>();
public SendSync(Transaction transaction) {
this.transaction = transaction;
}
public void add(ConnectionContext context, Message message) {
additions.add(new MessageContext(context, message));
}
@Override
public void beforeCommit() throws Exception {
synchronized (orderIndexUpdates) {
orderIndexUpdates.addLast(transaction);
}
}
@Override
public void afterCommit() throws Exception {
ArrayList<SendSync> syncs = new ArrayList<SendSync>(200);
sendLock.lockInterruptibly();
try {
synchronized (orderIndexUpdates) {
Transaction next = orderIndexUpdates.peek();
while( next!=null && next.isCommitted() ) {
syncs.add(sendSyncs.remove(orderIndexUpdates.removeFirst()));
next = orderIndexUpdates.peek();
}
}
for (SendSync sync : syncs) {
sync.processSend();
}
} finally {
sendLock.unlock();
}
for (SendSync sync : syncs) {
sync.processSent();
}
}
// called with sendLock
private void processSend() throws Exception {
for (Iterator<MessageContext> iterator = additions.iterator(); iterator.hasNext(); ) {
MessageContext messageContext = iterator.next();
// It could take while before we receive the commit
// op, by that time the message could have expired..
if (broker.isExpired(messageContext.message)) {
broker.messageExpired(messageContext.context, messageContext.message, null);
destinationStatistics.getExpired().increment();
iterator.remove();
continue;
}
sendMessage(messageContext.message);
messageContext.message.decrementReferenceCount();
}
}
private void processSent() throws Exception {
for (MessageContext messageContext : additions) {
messageSent(messageContext.context, messageContext.message);
}
}
@Override
public void afterRollback() throws Exception {
try {
for (MessageContext messageContext : additions) {
messageContext.message.decrementReferenceCount();
}
} finally {
sendSyncs.remove(transaction);
}
}
}
3. 那么 XA 事务又是什么呢?ActiveMQ 实现了分布式事务,当系统中存在多数据源的情况下,也许会需要使用 XA ,为了方便,只提供一个单数据源的例子:
Xid xid = new MyXid(1, new byte[]{0x01}, new byte[]{0x02});
session.getTransactionContext().start(xid, XAResource.TMSUCCESS);
// 操作mq
session.getTransactionContext().end(xid, XAResource.TMSUCCESS);
int prepare = session.getTransactionContext().prepare(xid);
System.out.println("prepare:" + prepare);
// 根据prepare结果决定是否提交
session.getTransactionContext().commit(xid, false);
这些操作步骤,和 MySQL的 XA 是一样的,也是 start,end,prepare,commit,实现的都是javax transaction 那一套接口。
public class MyXid implements Xid {
private int formatId;
private byte[] globalTid;
private byte[] branchQ;
public MyXid(int formatId, byte[] globalTid, byte[] branchQ) {
this.formatId = formatId;
this.globalTid = globalTid;
this.branchQ = branchQ;
}
public byte[] getBranchQualifier() {
return this.branchQ;
}
public int getFormatId() {
return formatId;
}
public byte[] getGlobalTransactionId() {
return this.globalTid;
}
}
ActiveMQ 事务和XA的更多相关文章
- ActiveMQ 事务、集群、持久订阅者、ActiveMQ监控
JMS介绍 JMS是什么? JMS的全称Java Message Service,既Java消息服务. JMS是SUN提供的旨在统一各种MOM(Message-Oriented Middleware) ...
- 分布式事务、XA、两阶段提交、一阶段提交
本文原文连接:http://blog.csdn.net/bluishglc/article/details/7612811 ,转载请注明出处! 1.XA XA是由X/Open组织提出的分布式事务的规范 ...
- 关于分布式事务,XA协议的学习笔记
XA分布式事务协议,包含二阶段提交(2PC),三阶段提交(3PC)两种实现. 1.二阶段提交方案:强一致性 事务的发起者称协调者,事务的执行者称参与者. 处理流程: 1.准备阶段 事务协调者,向所有事 ...
- jms中activemq事务探讨
http://blog.csdn.net/dly1580854879/article/details/68945997
- 如何实现XA式、非XA式Spring分布式事务
Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...
- 非XA式Spring分布式事务
Spring应用的几种事务处理机制 Java Transaction API和XA协议是Spring常用的分布式事务机制,不过你可以选择选择其他的实现方式.理想的实现取决于你的应用程序使用何种资源,你 ...
- MySQL数据库分布式事务XA优缺点与改进方案
1 MySQL 外部XA分析 1.1 作用分析 MySQL数据库外部XA可以用在分布式数据库代理层,实现对MySQL数据库的分布式事务支持,例如开源的代理工具:ameoba[4],网易的DDB,淘宝的 ...
- MySQL 中基于 XA 实现的分布式事务
1 XA协议 首先我们来简要看下分布式事务处理的XA规范可知XA规范中分布式事务有AP,RM,TM组成: 其中应用程序(Application Program ,简称AP):AP定义事务边界(定义事务 ...
- spring boot 分布式事务实现(XA方式)
关于spring boot 支持分布式事务,XA是常用的一种方式. 这里把相关的配置记下,方便以后使用. 首先配置两个不同的数据源 : 订单库.持仓库. /** * Created by zhangj ...
随机推荐
- C# winform窗体间传值(使用委托或事件)
窗体间传值 今天得空,刚好看到网上好多人再找winform窗体间传值的问题,由于昨天项目的优化的感觉不错,就写了个C# winform窗体间传值的demo,希望能给需要的人的带来帮助: 工程的源代码地 ...
- 宠物属性控制_pet
classIndex 职业索引 DmgAddPct 根据职业的法伤或攻强来计算宠物增加的物理伤害,增加的伤害值等于玩家法伤或攻强的百分比 SpAddPct 根据职业的法伤或攻强来计算宠物增加的法术伤害 ...
- 性能跃升50%!解密自主研发的金融级分布式关系数据库OceanBase 2.0
小蚂蚁说: 相信大家对蚂蚁金服自主研发的金融级分布式关系数据库OceanBase的故事不再陌生了.在刚刚过去的2018年天猫双11中,成交额2135亿再次创造了新纪录,而支撑今年双11的支付宝核心链路 ...
- 【BZOJ】3142: [Hnoi2013]数列
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3142 12年也有一个组合数学...(这几年的画风啊.... 考虑直接去做:DP? DP+容 ...
- hdu 3861 The King’s Problem trajan缩点+二分图匹配
The King’s Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- Qt5_选择文件对话框
1. 类似如下代码: QString fileName = QFileDialog::getOpenFileName( this, tr("Open File"), NULL,// ...
- [原][osg]Geometry详解
//geometry成员变量 PrimitiveSetList _primitives; osg::ref_ptr<Array> _vertexArray; //顶点 osg::ref_p ...
- linux c/c++ 文件是否存在
linux c/c++ 文件是否存在 #include <unistd.h> int FileExist(const char* fname) { return access(fname, ...
- 用aws cli 下载s3中数据到本地
参考https://blog.csdn.net/DynastyRumble/article/details/76649120 1 首先注册AWS账户,绑定信用卡.一定要填写正确的手机,因为验证方式是它 ...
- QT---事件系统
1 QT事件系统 1.1 事件的定义 QT中事件是有专门的类QEvent,常见的有键盘事件QKeyEvent.鼠标事件QMouseEvent和定时器事件QTimerEvent.例如用 ...