Overview

在单机托管的消息队列中,队列如果没有自调整,会有简单的顺序保证。而在分布式系统中, 消息队列的顺序无法保证,在著名系统 Kafka 中,在服务端实现了同分区下的顺序保证,在 Google 的 Pub/Sub 系统中,通过字段 OrderingKey 保证发送的顺序和接收的顺序是一致的,核心是相同 Key 的消息同步发送,对外提供统一的异步 Pub/Sub 模型。但是这些都需要使用消息队列的用户代码给予顺序保证,即用户代码自身提交的消息顺序是正确的。除此之外,无法提供可用性保证:当 Server 端 broken 的时候,当分区重调整的时候(Kafka),当引入 ACK 机制的时候(QoS 2),都可能扰乱顺序。以下提供一些关于消息队列的思考

顺序属性

发送与接收

消息在发送与接收的时候自然在现实世界中附有顺序属性。

时序

假设一个地区内系统希望保持消息有序,通过统一的时间(如原子钟)为消息增加时序属性。

  • 基于时序数据库的实现 Pub/Sub(Prometheus)

周期

任何系统都应该假设网络不是可靠的,为了实现相对可靠,需要付出一定的代价。

分布式跨客户端

维护一个强一致的周期统计系统,为需要保持顺序的一类消息签发周期数,以周期数维护各消息的相对顺序。针对一类消息分区

顺序调度

现在实现的调度器实现,通过检测 OrderingKey 字段,使相同 key 的消息保持顺序,不同 key 保持乱序。

自调整调度

在客户端使用队列批量提交,在提交前检测状态并自调整顺序。

消息窃取调度

当并发,异步发送的时候,闲置的线程或用户级线程(routine)通过消息窃取在不影响 Ordering 情况下加速发送。