作者:CHEN川
链接:http://www.jianshu.com/p/453c6e7ff81c
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
一、摘要
分布式消息系统作为实现分布式系统可扩展、可伸缩性的关键组件,需要具有高吞吐量、高可用等特点。而谈到消息系统的设计,就回避不了两个问题:
1、消息的顺序问题
2、消息的重复问题
二、关键特性以及其实现原理
2.1、顺序消息
要实现严格的顺序消息,简单且可行的办法就是:
保证生产者 - MQServer - 消费者是一对一对一的关系
这样的设计虽然简单易行,但也会存在一些很严重的问题,比如:
1、并行度就会成为消息系统的瓶颈(吞吐量不够)
2、更多的异常处理,比如:只要消费端出现问题,就会导致整个处理流程阻塞,我们不得不花费更多的精力来解决阻塞的问题。
但我们的最终目标是要集群的高容错性和高吞吐量。这似乎是一对不可调和的矛盾,那么阿里是如何解决的?
有些问题,看起来很重要,但实际上我们可以通过合理的设计或者将问题分解来规避。如果硬要把时间花在解决问题本身,实际上不仅效率低下,而且也是一种浪费。从这个角度来看消息的顺序问题,我们可以得出两个结论:
1、不关注乱序的应用实际大量存在
2、队列无序并不意味着消息无序
2.2、消息重复
上面在解决消息顺序问题时,引入了一个新的问题,就是消息重复。那么MQ是怎样解决消息重复的问题呢?还是“恰好”不解决。
造成消息的重复的根本原因是:网络不可达。只要通过网络交换数据,就无法避免这个问题。所以解决这个问题的办法就是不解决,转而绕过这个问题。那么问题就变成了:如果消费端收到两条一样的消息,应该怎样处理?
1、消费端处理消息的业务逻辑保持幂等性
2、保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现
第1条很好理解,只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样。第2条原理就是利用一张日志表来记录已经处理成功的消息的ID,如果新到的消息ID已经在日志表中,那么就不再处理这条消息。
我们可以看到第1条的解决方式,很明显应该在消费端实现,不属于消息系统要实现的功能。第2条可以消息系统实现,也可以业务端实现。正常情况下出现重复消息的概率不一定大,且由消息系统实现的话,肯定会对消息系统的吞吐量和高可用有影响,所以最好还是由业务端自己处理消息重复的问题,这也是MQ不解决消息重复的问题的原因。
MQ不保证消息不重复,如果你的业务需要保证严格的不重复消息,需要你自己在业务端去重。
三、阅读原文
在线观看地址:跟着阿笨一起玩NET
微信公众号:ABenDotNet