顺序消息:消息的有序是 消息消费时,可以按照发送的顺序进行消费。服务器
例如:假如生产者产生的两条消息M1 、M2 要保证两条消息的顺序来消费应该怎么作,咱们可能想到这样的场景:网络
M1发送到S1 , M2发送到S2,若是保证M1先于M2被消费,须要M1到达消费端后,通知S2 , 而后S2再将消息M2发送到消费端。设计
这个模式存在的问题是:若是M1,M2分别发送到两台Server,因为两台Server服务器的网络环境可能不一样,因此,不能保证M1先到达, 因此也就不能保证M1先被订阅者消费。那么就要在MQServer集群维护消息的顺序,如何解决:其中一种解决方式是把消息发送到同一台消息服务器上。队列
这样能够保证M1先于M2到达MQServer(客户端等到M1发送成功后再发送M2),根据先到达先消费的原则,M1会先于M2被消费,能保证顺序。效率
这个模型,理论上能够保证消息的顺序,但实际运行中你可能会遇到下面问题。集群
只要将消息从一台服务器发往另外一台服务器,就会出现网络延迟问题,如上图所示,若是发送M1耗时大于发送M2耗时,那么M2就先被消费,仍然不能保证消息的顺序,即便M1和M2同事到达消费端,因为不清楚消费端1和消费端2的负载状况,仍然有可能出现M2先于M1被消费。如何解决这个问题? 将M1和M2发往同一个消费者便可。且发送M1后,须要消费端响应成功后才能发送M2。并行
可是会引入另一个问题,若是发送M1后,消费端1没响应,那是继续发送M2呢 仍是从新发送M1?通常为了保证消息必定被消费,确定会选择重发M1到另一个消费端2,以下所示:方法
这样的模型就能保证严格的消息顺序了,可是消费端1没有响应Server时有两种状况,一种是M1确实没有到达,另一种状况是消费端1已响应。可是Server没收到。若是是第二种状况,重发M1,就会形成M1被重复消费,也就是咱们所说的 消息重复的问题。im
严格的顺序消息很是容易理解,并且处理问题也比较容易,要实现严格的顺序消息,简单且可行的方法就是:客户端
保证生产者-MQServer-消费者是一对一的关系
这样设计,并行度就成了消息系统的瓶颈(吞吐量不够),也会致使更多地异常处理,好比:只要消费端出现了问题,就会致使整个处理流程的阻塞,咱们不得不花费更多地经理来解决阻塞问题。
但咱们的最终目标是要集群的高容错性和高吞吐量。这彷佛是一对不可协调的矛盾,那么阿里是如何解决的?
世界上解决一个计算机问题字简单的方法:“刚好”不须要解决它! ——沈询
有些问题看起来重要,但实际上咱们能够经过合理的设计或者将问题分解来规避。若是硬要把时间花在解决它们身上,其实是浪费时间,效率 低下的,从这个角度来看消息的顺序问题,咱们能够得出两个结论:
- 不关注乱序的应用实际大量存在
- 队列无序并不意味着消息无序