简单了解Disruptor(一)

1.   Disruptor是什么

1.1   技术背景

LMAX是在英国注册并受到FCA监管(监管号码为509778)的外汇黄金交易所, LMAX架构是LMAX内部研发并应用到交易系统的一种技术。它之所以引起人们的关注,是因为它是一个非常高性能系统,这个系统是建立在JVM平台上,核心是一个业务逻辑处理器,官方号称它能够在一个线程里每秒处理6百万订单.

一个仅仅部署在4台服务器上的服务,每秒向Database写入数据超过100万行数据,每分钟产生超过1G的数据。而每台服务器(8核12G)上CPU占用不到100%,load不超过5。

1.2   对比阻塞队列

 可以和BlockingQueue做对比,不过disruptor除了能完成同样的工作场景外,能做更多的事,效率也更高。业务逻辑处理器完全是运行在内存中(in-memory),使用事件源驱动方式(event sourcing). 业务逻辑处理器的核心是Disruptors,这是一个并发组件,能够在无锁的情况下实现网络的Queue并发操作。LMAX的研究表明,现在的所谓高性能研究方向似乎和现代CPU设计是相左的。

The disruptor component provides asynchronous SEDA behavior much as the standard SEDA Component, but utilizes a Disruptor instead of a BlockingQueue utilized by the standard SEDA。

 

举例部分典型的使用方式:

说明: 2.0版本之后,Consumer的概念被EventProcessor代替,都是类似事件处理消费。

P=Producer, EP=Event processor,下面的模型中p代表了产生数据结构Event,EP代表消费数据Event,消费的过程中做逻辑处理。

* UniCast a series of items between 1 publisher and 1 event processor.
*
* +----+    +-----+
* | P1 |--->| EP1 |
* +----+    +-----+

* Produce an event replicated to two event processors and fold back to a single third event processor.
*
*           +-----+
*    +----->| EP1 |------+
*    |      +-----+      |
*    |                   v
* +----+              +-----+
* | P1 |              | EP3 |
* +----+              +-----+
*    |                   ^
*    |      +-----+      |
*    +----->| EP2 |------+
*           +-----+

* Pipeline a series of stages from a publisher to ultimate event processor.
* Each event processor depends on the output of the event processor.
*
* +----+    +-----+    +-----+    +-----+
* | P1 |--->| EP1 |--->| EP2 |--->| EP3 |
* +----+    +-----+    +-----+    +-----+

* MultiCast a series of items between 1 publisher and 3 event processors.
*
*           +-----+
*    +----->| EP1 |
*    |      +-----+
*    |
* +----+    +-----+
* | P1 |--->| EP2 |
* +----+    +-----+
*    |
*    |      +-----+
*    +----->| EP3 |
*           +-----+

* Sequence a series of events from multiple publishers going to one event processor.
*
* +----+
* | P1 |------+
* +----+      |
*             v
* +----+    +-----+
* | P1 |--->| EP1 |
* +----+    +-----+
*             ^
* +----+      |
* | P3 |------+
* +----+

....

官方代码examples有更多详细示例。

 

 

下面是官方给出的和ArrayBlockingQueue对比测试结果:

 Nehalem 2.8Ghz – Windows 7 SP1 64-bitSandy Bridge 2.2Ghz – Linux 2.6.38 64-bit
 ABQDisruptorABQDisruptor
Unicast: 1P – 1C5,339,25625,998,3364,057,45322,381,378
Pipeline: 1P – 3C2,128,91816,806,1572,006,90315,857,913
Sequencer: 3P – 1C5,539,53113,403,2682,056,11814,540,519
Multicast: 1P – 3C1,077,3849,377,871260,73310,860,121
Diamond: 1P – 3C2,113,94116,143,6132,082,72515,295,197

Comparative throughput (in ops per sec)

 

1.3   Disruptor构成

先介绍几个相关的核心概念。

  • 环形队列ringbuffer

数据缓冲区,不同线程之间传递数据的BUFFER。RingBuffer是存储消息的地方,通过一个名为cursor的Sequence对象指示队列的头,协调多个生产者向RingBuffer中添加消息,并用于在消费者端判断RingBuffer是否为空。巧妙的是,表示队列尾的Sequence并没有在RingBuffer中,而是由消费者维护。这样的好处是多个消费者处理消息的方式更加灵活,可以在一个RingBuffer上实现消息的单播,多播,流水线以及它们的组合。在RingBuffer中维护了一个名为gatingSequences的Sequence数组来跟踪相关Seqence。

  • Producer/Consumer

Producer即生产者,比如下图中的P1. 只是泛指调用 Disruptor 发布事件(我们把写入缓冲队列的一个元素定义为一个事件)的用户代码。

Consumer和EventProcessor是一个概念,新的版本中由EventProcessor概念替代了Consumer

有两种实现策略,一个是SingleThreadedStrategy(单线程策略)另一个是 MultiThreadedStrategy(多线程策略),两种策略对应的实现类为SingleProducerSequencer、MultiProducerSequencer【都实现了Sequencer类,之所以叫Sequencer是因为他们都是通过Sequence来实现数据写,Sequence的概念参见③】 ,它们定义在生产者和消费者之间快速、正确地传递数据的并发算法。具体使用哪个根据自己的场景来定,[多线程的策略使用了AtomicLong(Java提供的CAS操作),而单线程的使用long,没有锁也没有CAS。这意味着单线程版本会非常快,因为它只有一个生产者,不会产生序号上的冲突]

Producer生产event数据,EventHandler作为消费者消费event并进行逻辑处理。消费消息的进度通过Sequence来控制。

③Sequence

Sequence是一个递增的序号,说白了就是计数器;其次,由于需要在线程间共享,所以Sequence是引用传递,并且是线程安全的;再次,Sequence支持CAS操作;最后,为了提高效率,Sequence通过padding来避免伪共享,关于解决伪共享的问题,可以参见下面章节详细的介绍。

通过顺序递增的序号来编号管理通过其进行交换的数据(事件),对数据(事件)的处理过程总是沿着序号逐个递增处理。一个 Sequence 用于跟踪标识某个特定的事件处理者( RingBuffer/Consumer )的处理进度。生产者对RingBuffer的互斥访问,生产者与消费者之间的协调以及消费者之间的协调,都是通过Sequence实现。几乎每一个重要的组件都包含Sequence。

说明:虽然一个 AtomicLong 也可以用于标识进度,但定义 Sequence 来负责该问题还有另一个目的,那就是防止不同的 Sequence 之间的CPU缓存伪共享(Flase Sharing)问题。

 

④Sequence Barrier

用于保持对RingBuffer的 main published Sequence 和Consumer依赖的其它Consumer的 Sequence 的引用。 Sequence Barrier 还定义了决定 Consumer 是否还有可处理的事件的逻辑。SequenceBarrier用来在消费者之间以及消费者和RingBuffer之间建立依赖关系。在Disruptor中,依赖关系实际上指的是Sequence的大小关系,消费者A依赖于消费者B指的是消费者A的Sequence一定要小于等于消费者B的Sequence,这种大小关系决定了处理某个消息的先后顺序。因为所有消费者都依赖于RingBuffer,所以消费者的Sequence一定小于等于RingBuffer中名为cursor的Sequence,即消息一定是先被生产者放到Ringbuffer中,然后才能被消费者处理。不好理解的话,可以看下面章节事例配合了解。

SequenceBarrier在初始化的时候会收集需要依赖的组件的Sequence,RingBuffer的cursor会被自动的加入其中。需要依赖其他消费者和/或RingBuffer的消费者在消费下一个消息时,会先等待在SequenceBarrier上,直到所有被依赖的消费者和RingBuffer的Sequence大于等于这个消费者的Sequence。当被依赖的消费者或RingBuffer的Sequence有变化时,会通知SequenceBarrier唤醒等待在它上面的消费者。

 

⑤Wait Strategy

当消费者等待在SequenceBarrier上时,有许多可选的等待策略,不同的等待策略在延迟和CPU资源的占用上有所不同,可以视应用场景选择:

  • BusySpinWaitStrategy : 自旋等待,类似Linux Kernel使用的自旋锁。低延迟但同时对CPU资源的占用也多。
  • BlockingWaitStrategy : 使用锁和条件变量。CPU资源的占用少,延迟大。
  • SleepingWaitStrategy : 在多次循环尝试不成功后,选择让出CPU,等待下次调度,多次调度后仍不成功,尝试前睡眠一个纳秒级别的时间再尝试。这种策略平衡了延迟和CPU资源占用,但延迟不均匀。
  • YieldingWaitStrategy : 在多次循环尝试不成功后,选择让出CPU,等待下次调。平衡了延迟和CPU资源占用,但延迟也比较均匀。
  • PhasedBackoffWaitStrategy : 上面多种策略的综合,CPU资源的占用少,延迟大。

 

 

  • Event

在 Disruptor 的语义中,生产者和消费者之间进行交换的数据被称为事件(Event)。它不是一个被 Disruptor 定义的特定类型,而是由 Disruptor 的使用者定义并指定。

  • EventProcessor

EventProcessor 持有特定消费者(Consumer)的 Sequence,并提供用于调用事件处理实现的事件循环(Event Loop)。通过把EventProcessor提交到线程池来真正执行,有两类Processor:

其中一类消费者是BatchEvenProcessor。每个BatchEvenProcessor有一个Sequence,来记录自己消费RingBuffer中消息的情况。所以,一个消息必然会被每一个BatchEvenProcessor消费。

另一类消费者是WorkProcessor。每个WorkProcessor也有一个Sequence,多个WorkProcessor还共享一个Sequence用于互斥的访问RingBuffer。一个消息被一个WorkProcessor消费,就不会被共享一个Sequence的其他WorkProcessor消费。这个被WorkProcessor共享的Sequence相当于尾指针

 

  • EventHandler

Disruptor 定义的事件处理接口,由用户实现,用于处理事件,是 Consumer 的真正实现。开发者实现EventHandler,然后作为入参传递给EventProcessor的实例。

综上所述,附官方类图:

 转载自 并发编程网 - ifeve.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值