(一)初识Disruptor

作者: 伟仔1986 | 来源:发表于2018-05-07 22:15 被阅读12次

    通过这篇文章来记录和分享对Disruptor的初步了解认识Disruptor框架。

    Disruptor是什么?

    Disruptor是一个高性能的异步处理框架,或者可以认为是线程间通信的高效低延时的内存消息组件,它最大特点是高性能,其LMAX架构可以获得每秒6百万订单,用1微秒的延迟获得吞吐量为100K+。
    它是如何实现高性能的呢?它由于JDK内置的队列有什么区别呢?

    JDK内置内存队列?

    我们知道,Java内置了几种内存消息队列,如下所示:

    队列 加锁方式 是否有界 数据结构
    ArrayBlockingQueue 加锁 有界 ArrayList
    LinkedBlockingQueue 加锁 无界 LinkedList
    ConcurrentLinkedQueue CAS 无界 LinkedList
    LinkedTransferQueue CAS 无界 LinkedList

    我们知道CAS算法比通过加锁实现同步性能高很多,而上表可以看出基于CAS实现的队列都是无界的,而有界队列是通过同步实现的。在系统稳定性要求比较高的场景下,为了防止生产者速度过快,如果采用无界队列会最终导致内存溢出,只能选择有界队列。
    而有界队列只有ArrayBlockingQueue,该队列是通过加锁实现的,在请求锁和释放锁时对性能开销很大,这时候基于有界队列的高性能的Disruptor就应运而生。

    Disruptor如何实现高性能?

    Disruptor实现高性能主要体现了去掉了锁,采用CAS算法,同时内部通过环形队列实现有界队列。

    • 环形数据结构
      为了避免垃圾回收,采用数组而非链表。同时,数组对处理器的缓存机制更加友好。
    • 元素位置定位
      数组长度2^n,通过位运算,加快定位的速度。下标采取递增的形式。不用担心index溢出的问题。index是long类型,即使100万QPS的处理速度,也需要30万年才能用完。
    • 无锁设计
      每个生产者或者消费者线程,会先申请可以操作的元素在数组中的位置,申请到之后,直接在该位置写入或者读取数据。整个过程通过原子变量CAS,保证操作的线程安全。

    Disruptor可以用来做什么?

    当前业界开源组件使用Disruptor的包括Log4j2、Apache Storm等,它可以用来作为高性能的有界内存队列,基于生产者消费者模式,实现一个/多个生产者对应多个消费者。它也可以认为是观察者模式的一种实现,或者发布订阅模式。


    生产者消费者.png

    同时,Disruptor还允许开发者使用多线程技术去创建基于任务的工作流。Disruptor能用来并行创建任务,同时保证多个处理过程的有序性,并且它是没有锁的。

    工作流.png

    为什么要使用Disruptor?

    使用Disruptor,主要用于对性能要求高、延迟低的场景,它通过“榨干”机器的性能来换取处理的高性能。如果你的项目有对性能要求高,对延迟要求低的需求,并且需要一个无锁的有界队列,来实现生产者/消费者模式,那么Disruptor是你的不二选择。

    怎么用Disruptor?

    要学会基于Disruptor进行编程,我们先了解下大概流程示意图,其中绿色部分是表示我们需要编写和实现的类。


    Disruptor执行简图(2).png

    下面我们实现一个简单的用例,生产者负责将输入的字符串输出到队列,消费者负责打印出来。

    public class DisruptorTest {
        /**
         * 消息事件类
         */
        public static class MessageEvent{
            /**
             * 原始消息
             */
            private String message;
    
            public String getMessage() {
                return message;
            }
    
            public void setMessage(String message) {
                this.message = message;
            }
        }
    
        /**
         * 消息事件工厂类
         */
        public static class MessageEventFactory implements EventFactory<MessageEvent>{
            @Override
            public MessageEvent newInstance() {
                return new MessageEvent();
            }
        }
    
        /**
         * 消息转换类,负责将消息转换为事件
         */
        public static class MessageEventTranslator implements EventTranslatorOneArg<MessageEvent,String> {
            @Override
            public void translateTo(MessageEvent messageEvent, long l, String s) {
                messageEvent.setMessage(s);
            }
        }
    
        /**
         * 消费者线程工厂类
         */
        public static class MessageThreadFactory implements ThreadFactory{
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r,"Simple Disruptor Test Thread");
            }
        }
    
        /**
         * 消息事件处理类,这里只打印消息
         */
        public static class MessageEventHandler implements EventHandler<MessageEvent>{
            @Override
            public void onEvent(MessageEvent messageEvent, long l, boolean b) throws Exception {
                System.out.println(messageEvent.getMessage());
            }
        }
    
        /**
         * 异常处理类
         */
        public static class MessageExceptionHandler implements ExceptionHandler<MessageEvent>{
            @Override
            public void handleEventException(Throwable ex, long sequence, MessageEvent event) {
                ex.printStackTrace();
            }
    
            @Override
            public void handleOnStartException(Throwable ex) {
                ex.printStackTrace();
    
            }
    
            @Override
            public void handleOnShutdownException(Throwable ex) {
                ex.printStackTrace();
    
            }
        }
    
        /**
         * 消息生产者类
         */
        public static class MessageEventProducer{
            private RingBuffer<MessageEvent> ringBuffer;
    
            public MessageEventProducer(RingBuffer<MessageEvent> ringBuffer) {
                this.ringBuffer = ringBuffer;
            }
    
            /**
             * 将接收到的消息输出到ringBuffer
             * @param message
             */
            public void onData(String message){
                EventTranslatorOneArg<MessageEvent,String> translator = new MessageEventTranslator();
                ringBuffer.publishEvent(translator,message);
            }
        }
    
        public static void main(String[] args) {
            String message = "Hello Disruptor!";
            int ringBufferSize = 1024;//必须是2的N次方
            Disruptor<MessageEvent> disruptor = new Disruptor<MessageEvent>(new MessageEventFactory(),ringBufferSize,new MessageThreadFactory(),ProducerType.SINGLE,new BlockingWaitStrategy());
            disruptor.handleEventsWith(new MessageEventHandler());
            disruptor.setDefaultExceptionHandler(new MessageExceptionHandler());
            RingBuffer<MessageEvent> ringBuffer = disruptor.start();
            MessageEventProducer producer = new MessageEventProducer(ringBuffer);
            producer.onData(message);
        }
    }
    

    相关文章

      网友评论

        本文标题:(一)初识Disruptor

        本文链接:https://www.haomeiwen.com/subject/ftwjrftx.html