RabbitMQ
RabbitMQ 无法做到消息有序的原因:
1.RabbitMQ支持一个队列多个消费者进行消费,并行处理消息无法保证顺序。
2.RabbitMQ支持重试及超时重试机制,这也是导致无法顺序消费的原因(即使只有一个队列一个消费者 )。
RocketMQ
RabbitMQ 实现顺序消费:
1.需要有序的消息投入相同的队列,同时只有一个线程消费(但这个也无法100%解决,重试机制是个坑)。
2.RocketMQ只能保证消息的局部有序,无法保证全局有序。
3.RocketMQ 提供两种消费模式,一种是并行消费模式,另一种是顺序消费模式。当需要顺序消费时,只有保证需要保证顺序的消息进入同一个队列(指定队列),同时设置为顺序消费模式。
4.当设置为顺序消费模式时,消费方式会变成单线程模式,队列上锁。当消费失败时,当前线程会等待一个指定时间,然后再尝试消费这个消息。这个过程会无限次尝试直至消费成功。所以业务方需要做一定失败处理,当失败次达到一定次数,要返回SUCCESS,否则会一直卡在当前消息。
5.但也有个缺陷,在多主从的情况下,无法保证顺序消费。原因是多从的情况下,master之间互不通讯,当master宕机之后,消息会发往“活”的master,消费者也可能会转移消费其他“活”master对于的队列。
Kafka
Kafka 实现顺序消费:
1.Kafka 通过分区和多副本保证消息顺序,同时一个分区只能有一个消费者来消费,来保证消费顺序。
2.顺序消费的条件,将需要顺序消费的消息 通过 key 投入同一个分区。只要分区数量不变,Kafka就保证同一个key的消息,会被投入相同的分区(主分区宕机,会从副本中选举新的主分区)。( 且kafka 不支持重试)
总结
1.RocketMQ 和 RobbitMQ 想要实现消息的顺序消费,只能通过将消息投递的相同队列,同时只有一个消费者进行消费。但这样仍然无法100%保证,重试机制会将消息顺序打乱。
2.Kakfa 通过消息投入同一个分区,同时一个分区只会被一个消费者消费,来保证消费顺序。其主要实现的原理,一是Kafka保证了每个分区只能被一个消费者消费,二是Kafka实现一主多从机制,确保主分区至少和部分副分区同步,当主分区宕机,从重新选择"最新"的副分区做主分区,从而保证消费状态一致。
3.需要保证消息顺序的一致性,必定会限制消费速度,这时候可能通过业务技巧来提高消费速度(比如订单业务,可以将队列指定为 订单号%100, 开启100个消费者,分布订阅这一百个队列)。