Disruptor-源码解读

本文深入探讨Disruptor的源码,解析其高性能背后的原理。核心组件包括Ring Buffer、Sequencer(单生产者和多生产者)、消费者和等待策略。Disruptor利用锁、CAS、缓存行填充等技术实现高效的数据交换。同时,文章介绍了消费者之间的依赖关系、消费逻辑及启动流程。
摘要由CSDN通过智能技术生成

前言

Disruptor的高性能,是多种技术结合以及本身架构的结果。本文主要讲源码,涉及到的相关知识点需要读者自行去了解,以下列出:

  • 锁和CAS
  • 伪共享和缓存行
  • volatile和内存屏障

原理

此节结合demo来看更容易理解:传送门

下图来自官方文档

官方原图有点乱,我翻译一下

在讲原理前,先了解 Disruptor 定义的术语

  • Event

    存放数据的单位,对应 demo 中的 LongEvent

  • Ring Buffer

    环形数据缓冲区:这是一个首尾相接的环,用于存放 Event ,用于生产者往其存入数据和消费者从其拉取数据

  • Sequence

    序列:用于跟踪进度(生产进度、消费进度)

  • Sequencer

    Disruptor的核心,用于在生产者和消费者之间传递数据,有单生产者和多生产者两种实现。

  • Sequence Barrier

    序列屏障,消费者之间的依赖关系就靠序列屏障实现

  • Wait Strategy

  • 等待策略,消费者等待生产者将发布的策略

  • Event Processor

    事件处理器,循环从 RingBuffer 获取 Event 并执行 EventHandler。

  • Event Handler

    事件处理程序,也就是消费者

  • Producer

    生产者

Ring Buffer

环形数据缓冲区(RingBuffer),逻辑上是首尾相接的环,在代码中用数组来表示Object[]。Disruptor生产者发布分两步

  • 步骤一:申请写入 n 个元素,如果可以写入,这返回最大序列号
  • 步骤二:根据序列号去 RingBuffer 中获取 Event,修改并发布
RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();
// 获取下一个可用位置的下标(步骤1)
long sequence = ringBuffer.next();
try {
    // 返回可用位置的元素
    LongEvent event = ringBuffer.get(sequence);
    // 设置该位置元素的值
    event.set(l);
} finally {
    // 发布
    ringBuffer.publish(sequence);
}
复制代码

这两个步骤由 Sequencer 完成,分为单生产者和多生产者实现

Sequencer

单生产者

如果申请 2 个元素,则如下图所示(圆表示 RingBuffer)

// 一般不会有以下写法,这里为了讲解源码才使用next(2)
// 向RingBuffer申请两个元素
long sequence = ringBuffer.next(2);
for (long i =  sequence-1; i <= sequence; i++) {
    try {
        // 返回可用位置的元素
        LongEvent event = ringBuffer.get(i);
        // 设置该位置元素的值
        event.set(1);
    } finally {
        ringBuffer.publish(i);
    }
}
复制代码

next 申请成功的序列,cursor 消费者最大可用序列,gatingSequence 表示能申请的最大序列号。红色表示待发布,绿色表示已发布。申请相当于占位置,发布需要一个一个按顺序发布

如果 RingBuffer 满了呢,在上图步骤二的基础上,生产者发布了3个元素,消费者消费1个。此时生产者再申请 2个元素,就会变成下图所示

只剩下 1 个空间,但是要申请 2个元素,此时程序会自旋等待空间足够。

接下来结合代码看,单生产者的 Sequencer 实现为 SingleProducerSequencer,先看看构造方法

abstract class SingleProducerSequencerPad extends AbstractSequencer
{
    protected long p1, p2, p3, p4, p5, p6, p7;

    SingleProducerSequencerPad(int bufferSize, WaitStrategy waitStrategy)
    {
        super(bufferSize, waitStrategy);
    }
}

abstract class SingleProducerSequencerFields extends SingleProducerSequencerPad
{
    SingleProducerSequencerFields(int bufferSize, WaitStrategy waitStrategy)
    {
        super(bufferSize, waitStrategy);
    }

    long nextValue = Sequence.INITIAL_VALUE;
    long cachedValue = Sequence.INITIAL_VALUE;
}

public final class SingleProducerSequencer extends SingleProducerSequencerFields
{
    protected long p1, p2, p3, p4, p5, p6, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值