.NET分布式事务处理总结【下】 - 包含MSMQ的分布式事务处理
转自:http://www.cnblogs.com/daxnet/archive/2011/03/15/1984995.html
.NET直接提供对MSMQ的访问支持,只需要添加System.Messaging程序集引用即可方便地操作MSMQ。MSMQ支持两种事务处理模式:内部事务处理以及基于MS-DTC的分布式事务处理。
MSMQ的内部事务处理
MSMQ的内部事务处理是指,仅采用MSMQ本身提供的事务处理机制完成事务处理。比如,假设有一系列的消息需要发布到MSMQ,那么,就可以启动一个内部事务,确保这些消息的发布过程是一个原子操作。要使用MSMQ的内部事务处理机制,在创建消息队列的时候,就需要勾选“事务性”选项,如下图所示:
首先,需要创建一个MessageQueueTransaction的对象,并使用Begin调用以启动MSMQ的内部事务处理。然后,在MessageQueue的Send方法中,使用Send(object, MessageQueueTransaction)的重载函数发送消息,将创建好的MessageQueueTransaction对象作为第二个参数传递给Send方法;在完成所有消息的发送之后,使用MessageQueueTransaction对象的Commit方法提交事务。如果在发送消息的过程中遇到问题,则使用MessageQueueTransaction对象的Abort调用回滚事务。请参见下面的示例代码:
using (MessageQueue messageQueue = new MessageQueue(@".\private$\TPCDemoQueue",
false, false, QueueAccessMode.SendAndReceive))
{
MessageQueueTransaction trans = new MessageQueueTransaction();
try
{
trans.Begin();
for (int i = 0; i < 5; i++)
{
messageQueue.Send(new Message(i), trans);
}
trans.Commit();
}
catch
{
trans.Abort();
}
messageQueue.Close();
}
注意:如果你的消息队列在创建的时候没有设置“事务性”选项,那么,在完成消息队列的创建以后,你将无法修改该选项。更糟糕的是,在非事务性队列上执行上面的代码,则无法将消息发布到消息队列上,框架本身也不会提示任何错误信息,指示消息并未发布成功。
在分布式事务处理中使用MSMQ
在分布式事务处理的上下文中(比如,.NET 2.0+的TransactionScope中),上面所提到的MessageQueueTransaction将毫无用处,也就是说,MessageQueueTransaction与分布式事务处理毫无关系。你所要做的是,用正常的方式初始化一个MessageQueue的实例,然后,调用Send方法发布消息,在发布消息的时候,通过设置MessageQueueTransactionType的值来告诉MessageQueue,目前正处于一个分布式事务的上下文中。于是,你需要使用Send/Receive的重载方法:Send(object, MessageQueueTransactionType)以及Receive(MessageQueueTransactionType)。如下:
using (TransactionScope transaction = new TransactionScope())
{
Message inputMsg = inputQueue.Receive(MessageQueueTransactionType.Automatic);
// do some work
transaction.Complete();
}
注意:对于一些生命周期相对较长的事务处理,比如,假设你的用例是这样的:你首先需要从一个消息队列中获得消息,然后更新你的数据库记录,那么你的代码可能会是这样的:
using (TransactionScope transaction = new TransactionScope())
{
using (MessageQueue someQueue = new MessageQueue("<queue connection>"))
{
Message msg = someQueue.Receive();
// do something else
}
transaction.Complete();
}
这样做其实是不对的!因为Receive方法是一种同步调用,如果消息队列中根本没有任何内容,那么Receive调用就会被阻塞,直到消息队列中出现新的消息。这就意味着你的分布式事务一直都是处于开启的状态,而且可能由于等待时间过长而导致超时,最终导致一个MessageQueueException。
正确的做法是,在MessageQueue上使用BeginPeek调用(注意:不是BeginReceive方法,因为BeginReceive方法并不是用来处理事务性队列的),然后订阅PeekComplete事件,在事件处理过程中,再使用TransactionScope以及Receive等方法实现消息的获取。例如:
MessageQueue inputQueue = new MessageQueue("<queue connection>");
inputQueue.PeekCompleted += (s, e) =>
{
using (TransactionScope transaction = new TransactionScope())
{
Message inputMsg = inputQueue.Receive(MessageQueueTransactionType.Automatic);
// do some work
transaction.Complete();
}
inputQueue.BeginPeek();
};
inputQueue.BeginPeek();
最后再提醒一下,就是如果你所要做的事情仅限于与MSMQ打交道,那么只要使用MSMQ的内部事务处理机制就可以了,毕竟使用分布式事务处理会涉及到MS-DTC,从而造成过大的系统开销,影响性能。
.NET分布式事务处理总结【下】 - 包含MSMQ的分布式事务处理的更多相关文章
- Win7下单机版的伪分布式solrCloud环境搭建Tomcat+solr+zookeeper【转】
Win7下单机版的伪分布式solrCloud环境搭建Tomcat+solr+zookeeper 1.软件工具箱 在本文的实践中,需要用到以下的软件: Tomcat-7.0.62+solr-5.0.0+ ...
- VMwareWorkstation 平台 Ubuntu14 下安装配置 伪分布式 hadoop
VMwareWorkstation平台Ubuntu14下安装配置伪分布式hadoop 安装VmwareStation 内含注册机. 链接:https://pan.baidu.com/s/1j-vKgD ...
- [源码解析] PyTorch 分布式(3) ----- DataParallel(下)
[源码解析] PyTorch 分布式(3) ----- DataParallel(下) 目录 [源码解析] PyTorch 分布式(3) ----- DataParallel(下) 0x00 摘要 0 ...
- 【分布式事务】使用atomikos+jta解决分布式事务问题
一.前言 分布式事务,这个问题困惑了小编很久,在3个月之前,就间断性的研究分布式事务.从MQ方面,数据库事务方面,jta方面.近期终于成功了,使用JTA解决了分布式事务问题.先写一下心得,后面的二级提 ...
- Apache Ignite——集合分布式缓存、计算、存储的分布式框架
Apache Ignite内存数据组织平台是一个高性能.集成化.混合式的企业级分布式架构解决方案,核心价值在于可以帮助我们实现分布式架构透明化,开发人员根本不知道分布式技术的存在,可以使分布式缓存.计 ...
- 分布式缓存重建并发冲突和zookeeper分布式锁解决方案
如果缓存服务在本地的ehcache中都读取不到数据. 这个时候就意味着,需要重新到源头的服务中去拉去数据,拉取到数据之后,赶紧先给nginx的请求返回,同时将数据写入ehcache和redis中 分布 ...
- 分布式锁(3) ----- 基于zookeeper的分布式锁
分布式锁系列文章 分布式锁(1) ----- 介绍和基于数据库的分布式锁 分布式锁(2) ----- 基于redis的分布式锁 分布式锁(3) ----- 基于zookeeper的分布式锁 代码:ht ...
- 分布式锁(2) ----- 基于redis的分布式锁
分布式锁系列文章 分布式锁(1) ----- 介绍和基于数据库的分布式锁 分布式锁(2) ----- 基于redis的分布式锁 分布式锁(3) ----- 基于zookeeper的分布式锁 代码:ht ...
- 分布式服务:Dubbo+Zookeeper+Proxy+Restful 分布式架构
分布式 分布式服务:Dubbo+Zookeeper+Proxy+Restful 分布式消息中间件:KafKa+Flume+Zookeeper 分布式缓存:Redis 分布式文件:FastDFS ...
随机推荐
- virtualbox怎么装系统OVA虚拟包大全一键安装
1 第一步,下载ova虚拟包 http://pan.baidu.com/s/1hqxWkUo . 里面有win7.ubuntu.kali,你自己挑一个需要的 全都可以自动缩放屏幕,有VirtualBo ...
- 1003. Parity(并查集)
1003 看篇国家论文 <从<parity>的解法谈程序优化> 对于区间i,j 如果用sum[i],sum[j]来表示到i的1的个数的奇偶性 那么仔细想下 sum[i-1] 若 ...
- poj1151Atlantis(离散化+扫描线)
http://poj.org/problem?id=1151 http://www.cnblogs.com/kane0526/archive/2013/02/26/2934214.html这篇博客写的 ...
- [原]Unity3D深入浅出 - 新版动画系统(Mecanim)
Mecanim概述: Mecanim是Unity提供第一个丰富而复杂的动画系统,提供了: 针对人形角色的简易的工作流和动画创建能力 Retargeting(运动重定向)功能,即把动画从一个角色模型应用 ...
- ExtJs双ActionResult共用同一Js文件ID冲突解决方案
项目使用MVC+ExtJs实现,权限控制是基于Controller下的ActionResult的,有一个页面因参数不同就需要新建两个ActionResult. 不要问我为何是基于页面级,而不是数据级, ...
- memcached性能监控
在上文“在Windows .NET平台下使用Memcached”中,我给大家介绍了如何在Windows平台上部署Memecached服务端,如何在.NET平台中应用Memcached,详细介绍了两种流 ...
- Eclipse文件编码设置的问题
Eclipse中设置编码的方式 如果要使插件开发应用能有更好的国际化支持,能够最大程度的支持中文输出, 则最好使 Java文件使用UTF-8编码.然而,Eclipse工作空间(workspace)的缺 ...
- POJ 3377 Ferry Lanes
虽然它出现在dp专场里···但是我第一反应是一道最短路题···不过幸好它出现在dp专场里···因为我不怎么会dijstra什么的··· 题意:一条河上有N+1对码头,每个相邻码头之间需要一定时间到达, ...
- JSP文件上传代码
一.首先建立一个上传的界面,取名为a.jsp,代码如下 <%@ page contentType="text/html; charset=utf-8" language=&q ...
- keybd_event跟SendMessage,PostMessage模拟键盘消息的区别 z
首先你会发现keybd_event函数中是没有窗口句柄作为参数的,好奇的你一定会觉得很奇怪,那是因为,keybd_event是全局模拟按键的,只对前台窗口(即当前的活动窗口)才可以,但是如果模拟的按键 ...