rocketmq-baiji / rocketmq

Mirror of Apache RocketMQ
Apache License 2.0
4 stars 20 forks source link

【百技第3组】第三题:添加全局有序Consumer #23

Closed Root-lee closed 7 months ago

Root-lee commented 6 years ago

全局有序Consumer

问题描述:

RocketMQ的Topic的分队列存储的,队列内的消息按照发送时间有序,但是队列与队列之间消息无序,这会导致我们消费消息的时候,消息不是全局有序的。对于某些场景,如股票撮合,需要消息是全局有序的,由于保证消息的全局有序代价太大,当前RocketMQ是不支持消息全局有序消费的。实现这个全局有序的功能,目前有两种方案:

  1. 在Producer端将所有消息放进一个队列中,从而实现消费端消费消息全局有序。
  2. 全局对多个队列进行排序,将队列内有序队列间无序的消息按照时间戳进行排序,从而实现消费端消费消息的全局有序。

我们需要在客户端实现一个全局排序的OrderedConsumer以实现上述第2种方案。

解决思路:

  1. 单队列方法。

利用RocketMQ单个队列内保证有序的特点,在生产者端通过哈希将消息发送到单一的队列中。这样在消费者端,从队列内拉取的消息就是自然有序的。不好的地方就是,在生产者端,无法利用分布式计算的优势。这种方法适用于慢消费者的场景,多个消费者同时消费的速度和单一消息队列的速度相匹配。

  1. 单消费者方法。

单消费者的思想是在消费端只使用一个消费线程和消费者实例,通过消费者端保证全局顺序。具体做法是消费者从消息队列不断拉取新的消息,并在本地维护一个全局已排序但未消费的消息列队,然后再按顺序进行消费。不好的地方在于,在消费者端使用单线程和单实例,无法利用分布式计算的优势。这种方法适用于快消费者的场景,单个消费者消费速度和多个消息队列速度相匹配。

  1. 中间层全局排序后分发的方法。

https://images2018.cnblogs.com/blog/471426/201805/471426-20180519131253178-1043342972.png

受到PushConsumer的设计思路的启发,或许可以设计一个类似PullMessageService的中间层,在其中加入全局排序功能,得到全局有序的ProcessQueue,然后消费者端从有序的ProcessQueue上拉取消息进行消费。排序中间层可以设计在本地,对应多线程的使用场景,也可以设计成网络服务,对应分布式使用场景。不好的地方在于,由于添加了中间层,系统的设计更加复杂了,在网络时延和丢包的情况下,保证消息的顺序执行和正确不重复消费比较困难。

策略模式:

策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。

为了达到方便用户自有鉴权系统接入,同时能够为多种鉴权策略留足扩展的功能,我们采用设计模式中的策略模式进行实现。策略模式将一系列鉴权策略封装在一系列的策略类中,作为一个抽象策略类的子类,在不修改原有系统的基础上可以更换鉴权策略或者增加新的鉴权策略,它很好地管理一系列鉴权策略,提高了代码的复用性,将鉴权策略与我们当前代码进行解耦,实现鉴权策略的优雅替换。