High performance lock-free queue disruptor first experience

Source: Internet
Author: User
Tags server memory log4j

Original address: Haifeiwu and his friends ' blogs
Blog Address: www.hchstudio.cn
Welcome, please indicate the author and source, thank you!

Recently has been studying some problems in the queue, today the building mainly shares a high-performance queue disruptor.

What disruptor?

It is a high-performance queue developed by LMAX, a British foreign exchange trading Company, and is designed to solve memory queue latency issues. A single-threaded system based on the Disruptor development can support 6 million orders per second.

At present, many well-known projects, including Apache Storm and log4j2, have applied disruptor to achieve high performance. In the landlord company internal use disruptor and Netty combined to do GPS real-time data processing, the performance is quite powerful. This article from the actual combat point of view about the realization of disruptor principle.

Why Disruptor?

Disruptor the following design to solve the problem of slow queue speed:

    • Ring array Structure
      To avoid garbage collection, use arrays rather than linked lists. Because arrays are more friendly to the processor's caching mechanism.

    • Element position Positioning
      The length of the array is 2^n, and the speed of positioning is accelerated by bit operation. The subscript takes an incremental form. Don't worry about the index overflow issue. Index is a long type, even if 1 million QPS processing speed, it will take 300,000 years to run out.

    • Lock-Free Design
      Each producer or consumer thread first applies the position of the element in the array that can be manipulated, and then writes or reads the data directly at that location after applying to it.

    • Optimization for pseudo-sharing problems
      Disruptor eliminates this problem, at least for processor architectures where the cache row size is 64 bytes or less (it is possible that the processor's cache line is 128 bytes, then there is a pseudo-sharing problem with a 64-byte population), and by adding a complement to ensure that the ring The serial number of the buffer does not exist in a cache line with anything else.
How disruptor?

Through the above introduction, we can probably understand that disruptor is a high-performance lock-free queue, then how to use it, the following landlord through the disruptor to achieve a simple producer consumer model, introduce the use of disruptor

First, based on the Disruptor event-driven programming model, we need to define an event to carry the data.

public class DataEvent {    private long value;    public void set(long value) {        this.value = value;    }    public long getValue() {        return value;    }}

In order for Disruptor to pre-allocate these events for us, we need to construct a eventfactory to perform the construction

public class DataEventFactory implements EventFactory<DataEvent> {    @Override    public DataEvent newInstance() {        return new DataEvent();    }}

Once we have defined the event, we need to create a consumer that handles these events. In our case, all we have to do is print out the value from the console.

public class DataEventHandler implements EventHandler<DataEvent> {    @Override    public void onEvent(DataEvent dataEvent, long l, boolean b) throws Exception {        new DataEventConsumer(dataEvent);    }}

Next we need to initialize the disruptor and define a producer to generate the message

public class Disruptormanager {private final static Logger LOG = Loggerfactory.getlogger (Disruptormanager.class);    /* Consumer thread pool */private static executorservice ThreadPool;    private static disruptor<dataevent> disruptor;    private static ringbuffer<dataevent> Ringbuffer;    private static Atomiclong Datanum = new Atomiclong (); public static void Init (eventhandler<dataevent> EventHandler) {//initialize disruptor ThreadPool = executors.        Newcachedthreadpool (); Disruptor = new Disruptor<> (new Dataeventfactory (), 8 * 1024x768, ThreadPool, Producertype.multi, new Blockingwaitstrat        Egy ());        Ringbuffer = Disruptor.getringbuffer ();        Disruptor.handleeventswith (EventHandler);        Disruptor.start (); New Timer (). Schedule (new TimerTask () {@Override public void run () {Log.info ("number of put in queue")            According to number {}, queue remaining space {} ", Datanum.get (), ringbuffer.remainingcapacity ());    }}, New Date (), 60 * 1000); }    /** * * @param message */public static void Putdatatoqueue (Long message) {if (datanum.get () = =        Long.max_value) {datanum.set (0L);        }//Add an event to the queue long next = Ringbuffer.next ();            try {ringbuffer.get (next). Set (message);        Datanum.incrementandget ();        } catch (Exception e) {log.error ("deposit data to Ringbuffer [{}]" exception =>{} ", Message, E.getstacktrace ());        } finally {ringbuffer.publish (next);        }} public static void Close () {Threadpool.shutdown ();    Disruptor.shutdown (); }}

Finally, let's define a Main method to execute the code.

public class EventMain {    public static void main(String[] args) throws Exception {        DisruptorManager.init(new DataEventHandler());        for (long l = 0; true; l++) {            DisruptorManager.putDataToQueue(l);            Thread.sleep(1000);        }    }}

The above code specific interested in the small partner please visit github.com/haifeiwu/disruptor-learn

And then we can see the data that the console prints out.

Summary

The disruptor provides high performance in high concurrency situations with a compact, lock-free design.

In addition, the asynchronous mode in Log4j 2 uses the disruptor to handle. Here, the landlord encountered a small problem, is in the use of log4j 2 through the TCP mode to Logstash log data, due to network problems caused by the link interruption, resulting in log4j 2 continue to write data to Ringbuffer, ringbuffer data without consumers, Causes server memory to run full. The solution is to set the disruptor queue bounded in log4j 2, or switch to UDP mode to write log data (if the data is not important).

Reference links
    • High performance lock-free queue disruptor first experience
    • Anatomy disruptor: Why is it so fast? (ii) Magical cache line padding
    • High-performance Queue--disruptor

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.