原文
本文分享自华为云社区《RocketMQ 次序消费机制》,作者: 勇哥 java 实战分享 。
次序音讯是指关于一个指定的 Topic ,音讯严厉依照先进先出(FIFO)的准则进行音讯发布和消费,即先发布的音讯先消费,后发布的音讯后消费。
次序音讯分为分区次序音讯和大局次序音讯。
1、分区次序音讯
关于指定的一个 Topic ,一切音讯依据 Sharding Key 进行区块分区,同一个分区内的音讯依照严厉的先进先出(FIFO)准则进行发布和消费。同一分区内的音讯确保次序,不同分区之间的音讯次序不做要求。
- 适用场景:适用于功能要求高,以 Sharding Key 作为分区字段,在同一个区块中严厉地依照先进先出(FIFO)准则进行音讯发布和消费的场景。
- 示例:电商的订单创立,以订单 ID 作为 Sharding Key ,那么同一个订单相关的创立订单音讯、订单支付音讯、订单退款音讯、订单物流音讯都会依照发布的先后次序来消费。
2、大局次序音讯
关于指定的一个 Topic ,一切音讯依照严厉的先入先出(FIFO)的次序来发布和消费。
- 适用场景:适用于功能要求不高,一切的音讯严厉依照 FIFO 准则来发布和消费的场景。
- 示例:在证券处理中,以人民币兑换美元为 Topic,在价格相同的情况下,先出价者优先处理,则能够依照 FIFO 的方式发布和消费大局次序音讯。
大局次序音讯实际上是一种特殊的分区次序音讯,即 Topic 中只要一个分区,因而大局次序和分区次序的实现原理相同。
由于分区次序音讯有多个分区,所以分区次序音讯比大局次序音讯的并发度和功能更高。
音讯的次序需求由两个阶段确保:
- 音讯发送
如上图所示,A1、B1、A2、A3、B2、B3 是订单 A 和订单 B 的音讯产生的次序,业务上要求同一订单的音讯坚持次序,例如订单 A 的音讯发送和消费都依照 A1、A2、A3 的次序。
假设是普通音讯,订单 A 的音讯可能会被轮询发送到不同的行列中,不同行列的音讯将无法坚持次序,而次序音讯发送时 RocketMQ 支持将 Sharding Key 相同(例如同一订单号)的音讯序路由到一个行列中。
- 音讯消费
顾客消费音讯时,需求确保音讯消费次序和存储次序一致,终究实现消费次序和发布次序的一致。
咱们知道负载均衡服务是客户端开始消费的起点。在负载均衡阶段,并发消费和次序消费并没有什么大的不同,最大的不同在于:向Borker申请锁。
顾客依据分配的行列 messageQueue ,向 Borker 申请锁 ,假设申请成功,则会拉取音讯,假设失利,则守时使命每隔 20 秒会重新测验。
见上图,次序消费中心流程如下:
1、 组装成消费目标
2、 将恳求目标提交到消费线程池
和并发消费不同的是,这儿的消费恳求包含消费快照 processQueue ,音讯行列 messageQueue 两个目标,并不对音讯列表做任何处理。
3、 消费线程内,对消费行列加锁
4、 从消费快照中取得待消费的音讯列表
消费快照 processQueue 目标里,创立了一个红黑树目标 consumingMsgOrderlyTreeMap 用于临时存储的待消费的音讯。
5、 履行音讯监听器
履行监听器逻辑简单了解,消费快照的消费锁consumeLock的作用是:避免 Rebalance 线程把当前消费的 MessageQueue 目标移除掉。
6、 处理消费成果
消费成功时,首要计算需求提交的偏移量,然后更新本地消费进展。
消费失利时,分两种场景:
- 假设已消费次数小于最大重试次数,则将放入目标 consumingMsgOrderlyTreeMap 用例临时存储的待消费的音讯,重新加入到消费快照红黑树 msgTreeMap中,然后使用守时使命测验重新消费。
- 假设已消费次数大于等于最大重试次数,则将失利音讯发送到 Broker ,Broker 接收到音讯后,会加入到死信行列里,最后计算需求提交的偏移量,然后更新本地消费进展。
咱们做一个关于次序消费的总结:
- 次序消费需求由两个阶段音讯发送和音讯消费协同合作,底层支撑依靠的是 RocketMQ 的存储模型;
- 次序消费服务发动后,经过三把锁的机制,音讯行列 messageQueue 的数据都会被顾客实例单线程的履行消费;
- 假设顾客扩容,顾客重启,或者 Broker 宕机 ,次序消费也会有必定几率较短时间内乱序,所以顾客的业务逻辑还是要保障幂等。