Disruptor源码介绍(一)-RingBuffer

RingBuffer是Disruptor最重要的核心组件,可以理解为一个环形队列,用来存储事件,生产者往队列上面存放事件,消费者去读取。内部是如何实现的,我们来看下源码。

1.类结构

/**
 * Ring based store of reusable entries containing the data representing
 * an event being exchanged between event producer and {@link EventProcessor}s.
 *
 * @param  implementation storing the data for sharing during exchange or parallel coordination of an event.
 */
public final class RingBuffer extends RingBufferFields implements Cursored, EventSequencer, EventSink
看类的注释,翻译成中文就是:基于环形结构存储可重用条目包含一些数据,这些数据可以表示在事件生产者和EventProcessor之间交换的事件
可以看到RingBuffer实现了一系列接口Cursored, EventSequencer, EventSink,继承了RingBufferFields
我们来一个个看下接口:

1.1 Cursored

public interface Cursored
{
    /**
     * Get the current cursor value.
     *
     * @return current cursor value
     */
    long getCursor();
}

Cursored接口只提供了一个获取当前序列值(游标)的方法

1.2 EventSequencer

public interface EventSequencer extends DataProvider, Sequenced
{

}
看下DataProvider和Sequenced
1.2.1 DataProvider
public interface DataProvider
{
    T get(long sequence);
}
提供了一个根据序列号获得数据的方法
1.2.2 Sequenced
Sequenced定义的方法就比较多了,主要是跟序列有关,例如ringBuffer的size,下个发布事件的序列号等等

所以EventSequencer扩展了Sequenced,提供了一些序列功能;同时扩展了DataProvider,提供了按序列值来获取数据的功能。

1.3 EventSink
public interface EventSink
{
    /**
     * Publishes an event to the ring buffer.  It handles
     * claiming the next sequence, getting the current (uninitialised)
     * event from the ring buffer and publishing the claimed sequence
     * after translation.
     *
     * @param translator The user specified translation for the event
     */
    void publishEvent(EventTranslator translator);
...
}
EventSink主要提供发布事件的功能,发布事件就是指往ringBuffer上面放数据。
2.数据存储结构
abstract class RingBufferPad
{
    protected long p1, p2, p3, p4, p5, p6, p7;
}

abstract class RingBufferFields extends RingBufferPad
{
    private static final int BUFFER_PAD;
    private static final long REF_ARRAY_BASE;
    private static final int REF_ELEMENT_SHIFT;
    private static final Unsafe UNSAFE = Util.getUnsafe();

    static
    {
         //获取object数组元素的大小
        final int scale = UNSAFE.arrayIndexScale(Object[].class);
        if (4 == scale)
        {
            REF_ELEMENT_SHIFT = 2;
        }
        else if (8 == scale)
        {
            REF_ELEMENT_SHIFT = 3;
        }
        else
        {
            throw new IllegalStateException("Unknown pointer size");
        }
        BUFFER_PAD = 128 / scale;
        // Including the buffer pad in the array base offset 对象头的长度可以通过arrayBaseOffset获取
        REF_ARRAY_BASE = UNSAFE.arrayBaseOffset(Object[].class) + (BUFFER_PAD << REF_ELEMENT_SHIFT);
    }

    private final long indexMask;
    private final Object[] entries;
    protected final int bufferSize;
    protected final Sequencer sequencer;

    RingBufferFields(
        EventFactory eventFactory,
        Sequencer sequencer)
    {
        this.sequencer = sequencer;
        this.bufferSize = sequencer.getBufferSize();

        if (bufferSize < 1)
        {
            throw new IllegalArgumentException("bufferSize must not be less than 1");
        }
        if (Integer.bitCount(bufferSize) != 1)
        {
            throw new IllegalArgumentException("bufferSize must be a power of 2");
        }

        this.indexMask = bufferSize - 1;
       //entries数组长度比实际设置的bufferSize大,数组两侧都要填充BUFFER_PAD个空数据组位
        this.entries = new Object[sequencer.getBufferSize() + 2 * BUFFER_PAD];
        fill(eventFactory);
    }
// entries本身根据引用大小进行了填充,假设引用大小为4字节,BUFFER_PAD计算为32,数组两侧都要填充32个空数组位
    private void fill(EventFactory eventFactory)
    {
        for (int i = 0; i < bufferSize; i++)
        {
            entries[BUFFER_PAD + i] = eventFactory.newInstance();
        }
    }

     //根据填充的偏移量取值
    @SuppressWarnings("unchecked")
    protected final E elementAt(long sequence)
    {
        return (E) UNSAFE.getObject(entries, REF_ARRAY_BASE + ((sequence & indexMask) << REF_ELEMENT_SHIFT));
    }
}

/**
 * Ring based store of reusable entries containing the data representing
 * an event being exchanged between event producer and {@link EventProcessor}s.
 *
 * @param  implementation storing the data for sharing during exchange or parallel coordination of an event.
 */
public final class RingBuffer extends RingBufferFields implements Cursored, EventSequencer, EventSink
{
    public static final long INITIAL_CURSOR_VALUE = Sequence.INITIAL_VALUE;
    protected long p1, p2, p3, p4, p5, p6, p7;
RingBuffer的内存存储结构采用数据的形式Object[] entries,有保存数据长度的属性bufferSize,数据长度必须是2的次方,记录下标indexMask,还有一个Sequencer用来追踪Sequence,entries数组大小比传入的bufferSize要大,内部做了前后的空数据组位填充,避免伪共享发生,RingBuffer初始化会调用fill方法,预先根据传入的eventFactory预填充对应的事件数据,队列上面的事件可以不断被重复利用,不受GC的影响
伪共享的概念可以查这篇文章:http://ifeve.com/falsesharing/

那么如何创建RingBuffer实例,先看下构造方法,RingBuffer构造方法采用默认修饰符,对非本包屏蔽了构造方法,因此对外不能直接通过构造方法创建实例,提供方法如下

/**
 * Create a new Ring Buffer with the specified producer type (SINGLE or MULTI)
 *
 * @param  Class of the event stored in the ring buffer.
 * @param producerType producer type to use {@link ProducerType}.
 * @param factory      used to create events within the ring buffer.
 * @param bufferSize   number of elements to create within the ring buffer.
 * @param waitStrategy used to determine how to wait for new elements to become available.
 * @return a constructed ring buffer.
 * @throws IllegalArgumentException if bufferSize is less than 1 or not a power of 2
 */
public static  RingBuffer create(
    ProducerType producerType,
    EventFactory factory,
    int bufferSize,
    WaitStrategy waitStrategy)
{
    switch (producerType)
    {
        case SINGLE:
            return createSingleProducer(factory, bufferSize, waitStrategy);
        case MULTI:
            return createMultiProducer(factory, bufferSize, waitStrategy);
        default:
            throw new IllegalStateException(producerType.toString());
    }
}
public static  RingBuffer createSingleProducer(
    EventFactory factory,
    int bufferSize,
    WaitStrategy waitStrategy)
{
    SingleProducerSequencer sequencer = new SingleProducerSequencer(bufferSize, waitStrategy);

    return new RingBuffer(factory, sequencer);
}
public static  RingBuffer createMultiProducer(
    EventFactory factory,
    int bufferSize,
    WaitStrategy waitStrategy)
{
    MultiProducerSequencer sequencer = new MultiProducerSequencer(bufferSize, waitStrategy);

    return new RingBuffer(factory, sequencer);
}
根据单事件发布者和多事件发布者分别提供了对应的创建方法。
再看下RingBuffer其余的一些方法,也比较简单
/**
* 获取指定序列号上面的事件槽,有两个使用的地方,事件生产者和事件消费者申请到序列之后,都会通过这个方法生产或者发布事件
**/
@Override
public E get(long sequence)
{
    return elementAt(sequence);
}

/**
* 按照递增返回队列下一个序列号
**/
@Override
public long next()
{
    return sequencer.next();
}
/**
* 指定n个之后队列下一个序列号
**/
@Override
public long next(int n)
{
    return sequencer.next(n);
}
next系列的方法是通过内部的sequencer来实现的,next()的实现其实就是内部调用next(1)
@Override
public long tryNext() throws InsufficientCapacityException
{
    return sequencer.tryNext();
}

功能跟next类似,不同点在于next如果队列满了,会一直阻塞等待事件槽,而tryNext则会直接抛异常

public void addGatingSequences(Sequence... gatingSequences)
{
    sequencer.addGatingSequences(gatingSequences);
}

public long getMinimumGatingSequence()
{
    return sequencer.getMinimumSequence();
}

public boolean removeGatingSequence(Sequence sequence)
{
    return sequencer.removeGatingSequence(sequence);
}
追踪序列相关的方法


之后就是发布事件的方法,后续会详细讲解下发布事件的原理

@Override
public void publishEvent(EventTranslator translator)
{
    final long sequence = sequencer.next();
    translateAndPublish(translator, sequence);
}

private void translateAndPublish(EventTranslator translator, long sequence)
{
    try
    {
        translator.translateTo(get(sequence), sequence);
    }
    finally
    {
        sequencer.publish(sequence);
    }
}
事件发布分为三个步骤:1、申请序列 2、填充事件 3、提交序列
总结:
1.RingBuffer是Disruptor最核心的组件,负责生产者和消费组交互事件的存储,事件发布者发布事件放到RingBuffer 上面,事件处理者从RingBuffer上面取事件进行消费
2.RingBuffer可以认为是一个环形队列,内部存储结构为数组,为了避免伪共享,数组前后做了缓存行的填充,在CPU层面提升了性能,数据长度必须为2的幂,可以高效的取数据。
RingBuffer创建时对事件做了预填充处理,事件一直可以复用,不会被GC,避免了GC带来的性能影响








你可能感兴趣的:(Disruptor源码解析)