论坛首页 Java企业应用论坛

互联网网站架构升级----消息中间件的实现方案

浏览 20391 次
该帖已经被评为良好帖
作者 正文
   发表时间:2011-08-11  
表示看不懂.标记下 慢慢研究
0 请登录后投票
   发表时间:2011-08-12  
queue即消息队列,在MQ里它是基础的消息容器。几乎所有的MQ产品的topic的实现方式都是订阅者接收队列,再加上订阅机制。

信息集成里有个幂等的概念,即一个消息被消费一次和被消费多次产生相同的结果。如果消息具有幂等特性,即允许消息重复。消息无状态和幂等特性是应用系统应该遵守的原则,而后者往往被忽略。忽略后者的原因主要是过分相信(依赖)MQ的可靠性,其后果会造成业务数据的混乱,比丢失消息严重得多。

不确定的延时和消息不可达。发生这样的情况主要是网络因素造成的,MQ本身再可靠也无法避免这种情况发生。MQ提供了死信队列和Report机制(当消息不可达时给发送者发送报告消息),并结合消息的有效期和失败重试次数等属性来做可靠性补偿。其实这两种补偿措施对应用系统来说并不方便使用,同时也会增加系统成本。

相对分布式存储方案来说,MQ的可靠性不见得会更好。在MQ里发送端成功提交消息,也不能确保该消息在预期时间内成功送达目的地。在持久化方面,通常消息也不会确保写到磁盘上,这中间会有批量处理的机制和多级缓存的机制,否则性能无法满足需求(多数MQ也有确保成功写入磁盘的配置选项,但性能太差,基本都不会用。即使是数据库系统也是这样)。而分布式存储方案是靠复制多份数据来保证可靠性的。

MQ的集群模式的可靠性会大大降低。这里集群模式指的是负载均衡模式。这种模式主要强调的是高可用性、高伸缩性及高并发。负载均衡模式下丢消息、消息重复以及不确定延时的可能性会大大提高。可用性和可靠性本来就是矛盾的,难以二者兼顾。


MQ还有一个问题。在IBM的Websphere MQ的产品手册里有这样的描述,"不受时间约束的消息传递--应用程序能自如地交换信息,而无需考虑应用或服务在通讯时是否有效..."。这一特性是优点也是缺点。实际的实现是无需考虑服务是否有效,也无法判断服务是否有效。这一特性对现在的应用系统来说显得有些过时,大多数场合并不合适。这里不讨论实现原理,只说它的负面影响。如果在持续的一段时间内产生的消息数量远远大于服务端的消息消费能力,会在MQ系统中大量的积压消息,随着消息的不断积压,业务处理的延时持续增加,最终导致系统假死、系统超负荷后大面积交易失败甚至系统瘫痪。MQ系统的抗压能力不好,以至于许多使用MQ的架构设计中会写入类似“该架构不解决超过系统负荷的问题”的前提约束。这一缺陷显然不能适应现在的大规模互联网应用的需求。当然其他的解决方案也可能会遇到同样的问题。目前银行交易网关普遍使用MQ做前置设备,你可能经常会听说某网络交易高峰日银行网关瘫痪的新闻。

说了上面这么多主要是想强调应用不要也不能太相信(或依赖)MQ的可靠性。下面也该说说MQ的优点了。
MQ的性能应该也不算差,如果消息不大的话,比如1K消息,单个MQ节点的并发能力可以达到每秒一万条这个数量级。系统瓶颈往往在消费能力上,MQ的性能通常不是问题。
MQ产品从九十年代初的IBMMQ到现在已经发展了十多年了,它的成熟和稳定是能够保证的。
MQ有许多正式、非正式的工业化标准,这在异构化系统集成、遗留系统集成上尤为重要。
MQ产品针对复杂得网络(分布)环境提供更多的可靠性保证。
以MQ及其工业化标准为基础,已经有大量的周边产品及其系列的解决方案可供使用和参考。

MQ的许多特性及其可靠性保证是针对复杂网络(分布)环境的,如果消息系统是完全构建在稳定、可靠的私有网络内,并且没有遗留系统、各系统都能保证同时在线,是可以考虑使用其他的解决方案。
3 请登录后投票
   发表时间:2011-08-12  
javatracker 写道
akandfxs 写道
redis全部存在内存中,应该不会比第1,2种方案慢吧?
除非第一二种方案不是分布式的,全部走内部内存,不经过网络。


我的意思是如果作为一个DB看Redis的话不仅仅是内存,还要有持久化,甚至还要有master-slave结构,这样才能一定程度保证可靠性,如果完全用内存那可靠性就太差了,一般应用不太能接受;最起码也要Snapshotting持久!  这样就引起一系列问题了!


Nosql一般都有持久化,但是这个持久化一般在高可用性和可靠性中做衡量,只可做到其中一点。
MQ只用内存时效率最高,但是不可靠。
一般可靠性用文件或者直接用关系数据库来做持久,比如AMQ的file\kaha\jdbc
0 请登录后投票
   发表时间:2011-08-12  
晕,这么多人投我新手帖啊,看来这里高手很多啊
0 请登录后投票
   发表时间:2011-08-12  
javatracker 写道
晕,这么多人投我新手帖啊,看来这里高手很多啊


帮你投一票良好,拉回来。

像我们公司针对MQ也有自己的一个产品,实现方案有所不同:
1. 基于activemq的一个封装,在发送远程mqserver出现超时或者异常后,会直接写本地数据(使用了berkeleyDB嵌入式数据库),会定期将本地数据重新尝试发送到目标的mqserver
2. 如果需要严格的数据可靠性,写一条记录会同时往两台的mqserver上写消息。

用本地做mq fail存储,还有个比较头疼的就是消息的顺序性没法保证,业务系统上稍不注意就是个并发问题。不过目前他们也在尝试改进。

像诸如顺序性的解决,我们的另一个日子解析产品是利用文件append的方式进行处理,读取的时候顺序读取,还做了多份写(通过zookeeper协调读操作)。因为我们对日志有着严格的一致性需求,因为我们会尝试将日志在另一个目标上进行重现(所谓的跨机房数据库同步)。总的来说,根据系统需求应该有所取舍
3 请登录后投票
   发表时间:2011-08-13  
头疼。也不知道你纠结啥。。。。
消息中间件的缓存机制,也不能保证缓存的操作都能够安全的执行完毕,而且既然缓存了,也不能保证数据被时时关注,回馈消息能够时时被接收。
伴随时间的推移,消息执行的环境也会发生变化,对应到传统问题上或许叫做并发,而实际上因为缓存,可能不是并发而是延时导致的并发。如此情况发生的话,始终是无法保证消息执行结果会正确。
就如所有模型中的缓存部分,始终无法预知缓存的到底会有如何的结果,而问题是,用户如何知道缓存的这些消息最终回馈如何。
0 请登录后投票
   发表时间:2011-09-01  
基于硬盘的持久化的MQ系统,只依赖日志就能实现(AOF模式),别扯淡什么NOSQL,一点毛关系都没有
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics