LMAX的干扰器模式如何工作? [英] How does LMAX's disruptor pattern work?

查看:170
本文介绍了LMAX的干扰器模式如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解干扰器模式。我看了InfoQ的视频,试图阅读他们的论文。我理解有一个环形缓冲区涉及,它被初始化为一个极大的数组,以利用缓存局部性,消除新的内存分配。



这听起来像是有一个或多个原子整数跟踪位置。每个事件似乎获得一个唯一的id,它在环中的位置是通过找到其相对于环的大小等的模数找到的。



不幸的是,我没有直观的感觉如何工作。我做了许多交易应用程序,并研究了演员模型,看着SEDA等。



在他们的演示中他们提到这种模式基本上是如何路由器工作;



有更好的解释吗?

解决方案

Google代码项目参考技术文档< a>对环形缓冲区的实现,然而它是有点干燥,学术和艰难的人想要了解它是如何工作的。但是有一些博客文章已经开始以更可读的方式解释内部。有一个作为破坏者核心的环形缓冲区说明模式,消费者障碍的描述(部分与从破坏者读取)以及一些关于处理多个生产者的信息



Disruptor的最简单的描述是:它是一种以最有效的方式在线程之间发送消息的方式。



与队列相比:与队列相比,它可以用作队列的替代方案,但它也与SEDA和Actor共享许多功能。



Disruptor提供了将消息传递到另一个线程的能力,如果需要可以唤醒它(类似于BlockingQueue)。


  1. Disruptor的用户通过扩展Entry类并提供工厂来定义消息的存储方式预分配。这允许内存重用(复制),或者条目可以包含对另一个对象的引用。

  2. 将消息放入Disruptor是一个两阶段过程,首先在环形缓冲区,其向用户提供可以用适当数据填充的条目。然后必须提交条目,这种两阶段方法是必要的,以允许灵活地使用上述存储器。这是使消息对消费者线程可见的消息。

  3. 消费者有责任跟踪从环形缓冲区消耗的消息。将此职责从环形缓冲区本身移开有助于减少写入争用的数量,因为每个线程都维护自己的计数器。

与演员相比



Actor模型比大多数其他编程模型更接近Disruptor,特别是如果使用提供的BatchConsumer / BatchHandler类。这些类隐藏了维护消费序列号的所有复杂性,并在重要事件发生时提供一组简单的回调。


  1. Disruptor使用1个线程-1消费者模型,其中Actors使用N:M模型,即你可以有你喜欢的演员,他们将分布在固定数量的线程(通常每个核心一个)。

  2. BatchHandler接口提供了一个额外的)callback onEndOfBatch()。这允许缓慢的消费者,例如。那些对批量事件一起进行I / O以提高吞吐量的用户。可以在其他Actor框架中进行批处理,但是由于几乎所有其他框架在批处理结束时不提供回调,因此需要使用超时来确定批处理结束,从而导致延迟时间较差。 li>

与SEDA相比



模式来替代基于SEDA的方法。


  1. 它对SEDA提供的主要改进是并行工作的能力。为此,Disruptor支持向多个消费者多次投放相同的消息(以相同的顺序)。这避免了管道中需要fork阶段。

  2. 我们还允许消费者等待其他消费者的结果,而不必在他们之间放置另一个排队阶段。消费者可以简单地观察其依赖的消费者的序列号。


  3. 与内存屏障相比



    另一种思考的方式是结构化,有序的内存屏障。其中生产者障碍形成写入障碍,而消费者障碍是读取障碍。


    I am trying to understand the disruptor pattern. I have watched the InfoQ video and tried to read their paper. I understand there is a ring buffer involved, that it is initialized as an extremely large array to take advantage of cache locality, eliminate allocation of new memory.

    It sounds like there are one or more atomic integers which keep track of positions. Each 'event' seems to get a unique id and it's position in the ring is found by finding its modulus with respect to the size of the ring, etc., etc.

    Unfortunately, I don't have an intuitive sense of how it works. I have done many trading applications and studied the actor model, looked at SEDA, etc.

    In their presentation they mentioned that this pattern is basically how routers work; however I haven't found any good descriptions of how routers work either.

    Are there some good pointers to a better explanation?

    解决方案

    The Google Code project does reference a technical paper on the implementation of the ring buffer, however it is a bit dry, academic and tough going for someone wanting to learn how it works. However there are some blog posts that have started to explain the internals in a more readable way. There is an explanation of ring buffer that is the core of the disruptor pattern, a description of the consumer barriers (the part related to reading from the disruptor) and some information on handling multiple producers available.

    The simplest description of the Disruptor is: It is a way of sending messages between threads in the most efficient manner possible. It can be used as an alternative to a queue, but it also shares a number of features with SEDA and Actors.

    Compared to Queues:

    The Disruptor provides the ability to pass a message onto another threads, waking it up if required (similar to a BlockingQueue). However, there are 3 distinct differences.

    1. The user of the Disruptor defines how messages are stored by extending Entry class and providing a factory to do the preallocation. This allows for either memory reuse (copying) or the Entry could contain a reference to another object.
    2. Putting messages into the Disruptor is a 2-phase process, first a slot is claimed in the ring buffer, which provides the user with the Entry that can be filled with the appropriate data. Then the entry must be committed, this 2-phase approach is necessary to allow for the flexible use of memory mentioned above. It is the commit that makes the message visible to the consumer threads.
    3. It is the responsibility of the consumer to keep track of the messages that have been consumed from the ring buffer. Moving this responsibility away from the ring buffer itself helped reduce the amount of write contention as each thread maintains its own counter.

    Compared to Actors

    The Actor model is closer the Disruptor than most other programming models, especially if you use the BatchConsumer/BatchHandler classes that are provided. These classes hide all of the complexities of maintaining the consumed sequence numbers and provide a set of simple callbacks when important events occur. However, there are a couple of subtle differences.

    1. The Disruptor uses a 1 thread - 1 consumer model, where Actors use an N:M model i.e. you can have as many actors as you like and they will be distributed across a fixed numbers of threads (generally 1 per core).
    2. The BatchHandler interface provides an additional (and very important) callback onEndOfBatch(). This allows for slow consumers, e.g. those doing I/O to batch events together to improve throughput. It is possible to do batching in other Actor frameworks, however as nearly all other frameworks don't provide a callback at the end of the batch you need to use a timeout to determine the end of the batch, resulting in poor latency.

    Compared to SEDA

    LMAX built the Disruptor pattern to replace a SEDA based approach.

    1. The main improvement that it provided over SEDA was the ability to do work in parallel. To do this the Disruptor supports multi-casting the same messages (in the same order) to multiple consumers. This avoids the need for fork stages in the pipeline.
    2. We also allow consumers to wait on the results of other consumers without having to put another queuing stage between them. A consumer can simply watch the sequence number of a consumer that it is dependent on. This avoids the need for join stages in pipeline.

    Compared to Memory Barriers

    Another way to think about it is as a structured, ordered memory barrier. Where the producer barrier forms the write barrier and the consumer barrier is the read barrier.

    这篇关于LMAX的干扰器模式如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆