我正在尝试了解disruptor pattern。我已经看过InfoQ视频,并试图阅读他们的论文。我知道其中涉及一个环形缓冲区,它被初始化为一个非常大的数组,以利用缓存的局部性,消除新内存的分配。

听起来好像有一个或多个原子整数可以跟踪位置。每个“事件”似乎都有一个唯一的ID,并且可以通过找到其相对于环的大小等的模数来找到它在环中的位置。

不幸的是,我对它的工作方式没有直观的认识。我已经完成了许多交易应用程序,并研究了actor model,查看了SEDA等。

他们在演讲中提到,这种模式基本上就是路由器的工作方式。但是我也没有找到关于路由器工作方式的任何好的描述。

是否有一些更好的解释的好指针?

最佳答案

Google Code项目在环形缓冲区的实现上执行reference a technical paper,但是对于想要了解其工作原理的人来说,这有点干,学术性强。但是,有些博客文章开始以更易读的方式解释内部原理。有一个explanation of ring buffer是干扰器模式的核心,一个description of the consumer barriers(与从干扰器读取有关的部分)和一些information on handling multiple producers可用。

Disruptor的最简单描述是:这是一种以可能的最有效方式在线程之间发送消息的方式。它可以用作队列的替代方法,但是它也与SEDA和Actors共享许多功能。

与队列比较:

Disruptor提供了将消息传递到另一个线程的功能,并在需要时将其唤醒(类似于BlockingQueue)。但是,存在3个明显的差异。

  • Disruptor的用户通过扩展Entry类并提供工厂进行预分配来定义如何存储消息。这允许内存重用(复制),或者Entry可能包含对另一个对象的引用。
  • 将消息放入Disruptor是一个两阶段的过程,首先在环形缓冲区中声明一个插槽,该插槽为用户提供可以填充适当数据的条目。然后必须提交该条目,此2阶段方法对于允许灵活使用上述内存是必需的。正是提交使消息对使用者线程可见。
  • 使用者有责任跟踪已从环形缓冲区使用的消息。将责任从环形缓冲区本身移开有助于减少写争用的数量,因为每个线程都维护自己的计数器。

  • 与 Actor 相比

    Actor模型比大多数其他编程模型更接近Disruptor,特别是如果您使用提供的BatchConsumer / BatchHandler类。这些类隐藏了维护消耗的序列号的所有复杂性,并在发生重要事件时提供了一组简单的回调。但是,有一些细微的差异。
  • Disruptor使用1个线程-1个消费者模型,其中Actor使用N:M模型,即,您可以根据需要拥有任意数量的actor,它们将分布在固定数量的线程中(通常每个内核1个)。
  • BatchHandler接口(interface)提供了一个额外的(也是非常重要的)回调onEndOfBatch()。这允许缓慢的消费者,例如。那些执行I / O来批量处理事件以提高吞吐量的人。可以在其他Actor框架中进行批处理,但是由于几乎所有其他框架在批处理结束时都没有提供回调,因此您需要使用超时来确定批处理结束,从而导致延迟时间长。

  • 与SEDA 相比

    LMAX构建了Disruptor模式来取代基于SEDA的方法。
  • 与SEDA相比,它提供的主要改进是并行工作的能力。为此,Disruptor支持将相同的消息(以相同的顺序)多播到多个使用者。这避免了在管道中需要派生阶段。
  • 我们还允许消费者等待其他消费者的结果,而不必在他们之间放置另一个排队阶段。使用者可以简单地查看其所依赖的使用者的序列号。这避免了在管道中加入阶段的需要。

  • 与内存屏障相比

    考虑它的另一种方法是将其作为结构化的有序内存屏障。生产者壁垒形成写壁垒,而消费者壁垒是读壁垒。

    关于concurrency - LMAX的破坏者模式如何工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6559308/

    10-11 07:03