`
in355hz
  • 浏览: 229869 次
社区版块
存档分类
最新评论

Disruptor 全解析(1):Ring Buffer 有什么特别?

阅读更多
原文地址: http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html​  作者是 Trisha Gee, LMAX 公司的一位女工程师。
 
最近我们开源了 LMAX Disruptor​,它是让我们的交易流程变得如此之快的关键。为什么要开源它?因为我们意识到大家对高性能编程的传统认知 ... 有些不对劲。我们找到了一个更好的,更快的在线程间共享数据的方法,如果不把它分享给大家就太自私了。而且,这会使我们看起来很酷。

从这个 网站​ 你可以下载一份解释什么是 Disruptor,以及它为什么如此巧妙和飞快的技术文档。我从这里得到了一些写作帮助,其实我真正做的只是在上面加了一些标点和重新组织了一些我不明白的句子,这太简单了。
 
我发现要把这些东西一次性解释清楚有些困难,所以我准备一小段一小段的解释它们,以适合我的 NADD​ 听众。

首先 - Ring Buffer。我对 Disruptor 的最初印象只有 Ring Buffer。后来我渐渐明白 Ring Buffer 结构是这个模式的中心,关键之处是 Disruptor 如何控制对它的访问。

Ring Buffer 究竟是什么?

正如名字描述那样 - 它是一个环 (圆形,首尾相接的),你可以把它当作一个缓存 (buffer),用来在一个线程上下文与另一个线程上下文之间传递数据。
 
Disruptor 全解析(1):Ring Buffer 有什么特别?
(好吧,我是用 Paint 画的。我尝试画草图,希望强迫症没有掺和进来要求我画出完美的圆和直线)。

所以基本上 Ring Buffer 就是拥有一个序号指向下一个可用元素的数组。
 
Disruptor 全解析(1):Ring Buffer 有什么特别?
 
如果你持续向 buffer 中写入数据(应该也会从里面读数据),这个序号会一直增长,直到绕过整个环。
 
Disruptor 全解析(1):Ring Buffer 有什么特别?

要找到数组中当前序号指向的元素,你可以用 mod 运算。

sequence mod array length = array index

因此对于上面的 Ring Buffer,这个算法就是(用 JAVA 的 mod 语法):12 % 10 = 2。很简单。

 

其实图片里画着 10 个元素完全是一个意外。2 的 N 次方个元素会更好,因为计算机是用二进制思考的。

接下来呢? 

如果你从 Wikipedia 查到 Circular Buffers​,你会看到它与我们的实现方式有一个重要的差别-没有指向末尾的指针。我们只有下一个可用的序号。这是刻意的-选择 Ring Buffer 的根本原因是需要支持可靠的消息通信。我们需要把服务发出的消息存储起来,那么当另一个服务发来一个 NAK (拒绝应答信号)​​ 说他们没有收到消息的时候,我们可以重新发送给他们。

 

Ring Buffer 看起来很理想。它用序号来指出 buffer 的末尾在哪里,而且当它收到一个 NAK 信号的时候,可以重发从那一点到当前序号之间的所有消息:

 

 

Disruptor 全解析(1):Ring Buffer 有什么特别?

 

 

我们所实现的 Ring Buffer 与传统队列的区别是:buffer 里的对象不会被销毁-它们留在那儿直到下次被覆盖写入。这是与 Wikipedia 上的版本相比我们的实现不需要尾指针的原因。在我们的实现中,确定 Ring Buffer 是否重叠的工作,是由数据结构之外来完成的(这是生产者与消费者行为的一部分-如果你来不及等我写博客说明它,可以自己检出 Disruptor 代码​​)。

 

Ring Buffer 这么棒是因为...?

 

我们使用 Ring Buffer 这种数据结构,是因为它给我们提供了可靠的消息传递特性。这个理由就足够了,不过它还有一些其他的优点。


首先,Ring Buffer 比链表要快,因为它是数组,而且有一个容易预测的访问模式。这很不错,对 CPU 高速缓存友好 (CPU-cache-friendly)-数据可以在硬件层面预加载到高速缓存,因此 CPU 不需要经常回到主内存 RAM 里去寻找 Ring Buffer 的下一条数据。


第二点,Ring Buffer 是一个数组,你可以预先分配内存,并保持数组元素永远有效。这意味着内存垃圾收集(GC)在这种情况下几乎什么也不用做。此外,也不像链表那样每增加一条数据都要创建对象-当这些数据从链表里删除时,这些对象都要被清理掉。

 

文章缺少的部分


我没有提到如何避免环重叠,以及怎么向 Ring Buffer 读、写数据的细节。你也会注意到我在拿它和链表那样的数据结构相比较,我想没人会认为链表是实际问题的解决方案。

有趣的部分来自于拿 Disruptor 和队列之类的实现相比较。队列通常关注于维护队列的头和尾,添加和消费消息一类的东西。所有这些东西我还没有在 Ring Buffer 一节真正提到。这是因为 Ring Buffer 本身并不负责这些事情,我们把这些问题挪到了数据结构的外部。

你可以到这个 网站​ 阅读论文或检出代码获得更详细的信息。也可以去看 Mike 和 Martin去年在 QCon San Francisco 的演讲​。或者,再等我 5 分钟来想想怎么讲后面剩下的东西。

分享到:
评论

相关推荐

    LMAX disruptor jar包+Demo+Api+src源码 disruptor-3.0.1.jar

    - 一个简单的Disruptor示例通常包括创建Disruptor对象、初始化Ring Buffer、设置Producer和Consumer,以及启动处理循环。通过示例,开发者可以快速上手,理解Disruptor的工作流程。 综上所述,LMAX Disruptor是一...

    Disruptor并发框架中文参考文档

    ##### 2.1 Ring Buffer的特别之处 Ring Buffer是Disruptor的核心组件,它是一个固定大小的循环数组。Ring Buffer的设计使得生产者和消费者可以在不使用锁的情况下进行通信。Ring Buffer使用两个指针(头指针和尾...

    disruptor技术培训

    5. **启动Disruptor**:获取RingBuffer实例,并通过它来生产数据。 6. **处理数据**:数据被自动发布到RingBuffer,并由相应的消费者进行处理。 通过以上步骤,我们就可以构建一个基于Disruptor的高性能并发处理...

    高并发框架Disruptor代码

    1. **Ring Buffer**:Disruptor的核心是环形缓冲区(Ring Buffer),它是一个固定大小的数组,用于存储待处理的事件。环形结构避免了头尾指针的同步问题,提高了效率。 2. **Sequencer**:Sequencer负责为事件分配...

    Disruptor报错FatalExceptionHandler的解决办法,看网上这种解决办法挺少,整理了一下

    Disruptor是一款高性能的并发框架,它通过使用Ring Buffer和基于事件的处理方式来消除锁竞争,提升系统性能。在使用Disruptor过程中,开发者可能会遇到`FatalExceptionHandler`的错误,这通常是由于处理流程中的异常...

    DisruptorDemo.zip

    3. 环形缓冲区(RingBuffer):存储数据的容器,采用循环数组实现,确保空间利用率。 4. 事件处理器(EventHandler):消费者处理数据的逻辑封装,每个消费者可以注册多个事件处理器。 5. 事件处理器组...

    spring-boot-starter-disruptor.zip

    Disruptor是由LMAX公司开源的一款并发框架,其设计灵感来源于传统的消息队列,但通过独特的环形缓冲区(Ring Buffer)和事件处理机制,显著提升了并发性能,特别适用于高吞吐量、低延迟的场景。Disruptor的核心思想是...

    disruptor 代码分析

    Disruptor框架是LMAX交易所开源的一个高性能、低延迟的消息队列实现,它采用无锁化编程技术,利用环形缓冲区(Ring Buffer)来实现高效的多生产者多消费者模型。本文将深入分析Disruptor的代码,特别聚焦于`...

    SourceAnalysis_Disruptor:Disruptor原始码解析-源码解析

    它采用环形缓冲区(Ring Buffer)作为主要的数据结构,结合生产者-消费者模型,实现了高效的事件处理机制。这种设计模式可以极大地减少数据同步的成本,从而达到微秒级别的消息传递速度。 二、环形缓冲区 环形缓冲...

    Disruptor并行框架面试题收录

    - **定义**:Disruptor使用RingBuffer作为存储事件的主要数据结构。它是一个固定大小的循环数组,用于存储由生产者产生的事件。 - **特点**: - **固定大小**:初始化时确定大小,通常为2的幂次方,以便利用位...

    disruptor-starter:干扰器的使用示例

    Disruptor的核心在于它的环形缓冲区(Ring Buffer),这个缓冲区在多个处理器之间共享,通过序列化事件的生产与消费,使得数据传递无需锁操作,从而减少了上下文切换和内存同步的成本。 标签"Java"表明Disruptor是...

    disruptor-3.2.1.zip

    Disruptor-3.2.1是由LMAX公司开发并开源的一款高性能的并发框架,其核心是一个环形缓冲区(Ring Buffer)。这个框架的设计理念是消除多线程之间的锁竞争,从而大幅度提高系统的处理速度。在3.2.1版本中,Disruptor...

    myDisruptor.zip

    首先,Disruptor的核心概念是“Ring Buffer”,一个固定大小的循环缓冲区。在myDisruptor.zip中,我们看到的就是这个关键组件的实现。Ring Buffer由一系列元素组成,每个元素都有一个唯一的序号,生产者和消费者通过...

    disruptor:LMAX干扰器的C++实现

    首先,我们要理解Disruptor的核心——环形缓冲区(Ring Buffer)。这个数据结构是一种固定大小的数组,用于存储待处理的事件。在C++实现中,环形缓冲区通常使用原子操作和内存屏障来保证在多线程环境下的正确性,...

    高性能高稳定性分布式的游戏架构,游戏逻辑运行在Disruptor消费者线程中,其它线程都为辅助线程, 整体为多生产者.zip

    Disruptor的环形缓冲区(Ring Buffer)设计能够减少数据在内存中的复制,进一步提升了处理速度。同时,其多生产者模型允许来自不同源头的数据并行写入,而单消费者模型则可以高效地顺序处理这些事件,确保了游戏逻辑...

    disruptorEx

    由LMAX公司开源的Disruptor,是专为高性能交易系统设计的一种并发数据结构,它的核心是一个环形缓冲区(Ring Buffer),通过消除锁和线程上下文切换,实现了高吞吐量的数据传递。本文将深入探讨DisruptorEx,解析其...

    破坏者:高性能线程间消息传递库

    Disruptor的核心理念在于使用一个环形缓冲区(Ring Buffer)来存储待处理的消息,这个环形缓冲区是由固定大小的槽位组成,每个槽位代表一个消息单元。生产者线程将消息放入缓冲区,而消费者线程则从缓冲区取出并处理...

Global site tag (gtag.js) - Google Analytics