Introduction to Disruptor - First understanding of the Disruptor framework

Introduction to Disruptor:

LMAX Disruptor is a high-performance inter-thread message library. It originated from LMAX's research on concurrency, performance and non-blocking algorithms, and now constitutes the core part of the Exchange infrastructure.

  • Disruptor is an open source concurrency framework, and won the 2011 Duke's Program Framework Innovation Award, which can implement concurrent network Queue operations without locks.

  • Disruptor is a high-performance asynchronous processing framework, or it can be considered the fastest messaging framework (lightweight JMS), it can also be considered an implementation of the observer mode, or the implementation of the event monitoring mode.

Here you can compare with the BlockingQueue queue, simply understand that it is an efficient "producer-consumer" model, first understand the underlying principles.

The core concept of Disruptor:

  • Ring Buffer, as its name suggests, is a ring buffer. RingBuffer used to be the most important object in Disruptor, but starting from version 3.0, its responsibilities have been reduced to only being responsible for storing and updating data (events) exchanged through Disruptor. In some more advanced application scenarios, Ring Buffer can be completely replaced by user-defined implementations.
  • Sequence Disruptor numbers and manages the data (events) exchanged through it through sequentially increasing sequence numbers, and the processing of data (events) always increases one by one along the sequence number. A Sequence is used to track the processing progress of a specific event handler (RingBuffer/Consumer). Although an AtomicLong can also be used to identify progress, there is another purpose of defining a Sequence to be responsible for the problem, which is to prevent the CPU cache false sharing (Flase Sharing) problem between different Sequences.
  • Sequencer Sequencer is the real core of Disruptor. This interface has two implementation classes, SingleProducerSequencer and MultiProducerSequencer, which define concurrent algorithms for transmitting data quickly and correctly between producers and consumers.
  • Sequence Barrier is used to keep references to the main published Sequence of the RingBuffer and the Sequence of other Consumers that the Consumer depends on. Sequence Barrier also defines the logic to determine whether the Consumer still has events that can be processed.
  • Wait Strategy defines how the Consumer waits for the next event strategy. (Note: Disruptor defines a variety of different strategies and provides different performance for different scenarios)
  • Event In the semantics of Disruptor, the data exchanged between the producer and the consumer is called an event. It is not a specific type defined by the Disruptor, but is defined and specified by the user of the Disruptor.
  • EventProcessor EventProcessor holds the Sequence of a specific consumer (Consumer) and provides an event loop (Event Loop) used to call the implementation of event processing.
  • The event processing interface defined by EventHandler Disruptor is implemented by the user and used to process events. It is the real realization of Consumer.
  • Producer refers to the user code that calls the Disruptor to publish events. The Disruptor does not define a specific interface or type.

Simple implementation of Disruptor code

Let's take a simple example to implement the Disruptor: the producer passes a long type variable to the consumer, and the consumer prints the variable.

Single producer, single consumer model:

(1) The event element inserted into the ringbuffer: a long variable is placed in the object

public class LongEvent {

    private long value;

    public long getValue() {
        return value;
    }

    public void setValue(long value) {
        this.value = value;
    }
}

(2) Event production factory: production events are stored in ringbuffer

public class LongEventFactory implements EventFactory<LongEvent> {

    public LongEvent newInstance() {
        return new LongEvent();
    }
}

(3) The event handler, that is, the consumer, prints out the value of the event

public class LongEventHandler implements EventHandler<LongEvent> {

    public void onEvent(LongEvent event, long sequence, boolean endOfBatch) throws Exception {
        System.out.println("Event:"+event.getValue());
    }
}

(4) Main function: create a producer and fill the ringbuffer with elements

public class DisruptorMain {

    public static void main(String[] agrs) throws InterruptedException {

        //创建线程池:
        Executor executor = Executors.newCachedThreadPool();

        //事件生产工厂:
        LongEventFactory longEventFactory = new LongEventFactory();

        //ringbuffer的大小:
        int bufferSize = 256;

        //实例化disruptor对象:初始化ringbuffer
         Disruptor<LongEvent> disruptor = new Disruptor<LongEvent>(longEventFactory, bufferSize, executor,ProducerType.SINGLE, new BlockingWaitStrategy());

        //设置事件的执行者:(单消费者)
        disruptor.handleEventsWith(new LongEventHandler());

        //disruptor启动:
        disruptor.start();

        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer();

        //设置事件单生产者:
        for(int x = 0;x<256; x++){
            // 获取下一个可用位置的下标
            long sequence = ringBuffer.next();  
            try{
                // 返回可用位置的元素
                LongEvent event = ringBuffer.get(sequence); 
                // 设置该位置元素的值
                event.set(x); 
            }finally{
                //发布事件 
                ringBuffer.publish(sequence);
            }
            Thread.sleep(10);
        }
    }
}

 

For the integration of Disruptor framework and SpringBoot, please refer to Spring boot integration disruptor

 

 

Guess you like

Origin blog.csdn.net/Crystalqy/article/details/107260128