Disruptor是一个MQ,其中的Queue是一个ring buffer。

对于queue来说有三个问题需要关注:

  1. 被交换项的存储
  2. 声明下一个交换的sequence,用于协调生产者们
  3. 通知新的交换项可获得,用于协调消费者们
  • 针对1,预先分配固定大小的queue,好处是可以减少GC的影响,更好的利用cache。
  • 针对2,对于单生产者,获取序列号没有竞争的问题;对于多生产者,使用CAS操作来获取序列号。
  • 针对3,对于消费者们来说就没有竞争的问题了。可以按照CPU资源的稀缺度,或者使用信号通知模式,或者使用循环检查模式。

可见sequence在并发管理中处于核心地位。

在生产者这边,如果是单生产者没有竞争写的问题;如果是多生产者,可以用CAS解决竞争的问题。写完之后,需要更新一个独立的计数器cursor指明最近一个可获得的消息项,这里只需要使用memory barrier,而不需要CAS操作。

在消费者这边,消费者通过使用memory barrier读cursor来等待新的消息项。消费者也有自己的sequence,生产者可以通过读这个sequence来防止覆盖ring上未处理的消息,消费者们也可以通过各自的sequence来协调消费者们的处理顺序。

对于传统的SEDA,不同的stage之间都需要queue,但是对于Disruptor来说,复杂的依赖图完全可以基于一个ringe buffer来实现,这极大的提高了吞吐量,减少了延迟。对于某些stage处于落后的状态,可以使用batch处理的方式迅速赶上来。