Disruptor原理分析


一 简介

Disruptor是一个性能极强的异步消息处理框架,可以认为它是线程间通信高效低延时的内存消息组件,它最大的特点是高性能,其LMAX架构可以获得每秒6百万订单,用1微秒的延迟获得吞吐量为100K+。实际上它是拿内存换取处理高性能的低延迟的处理熟速度,
(实际上这个框架在log4j,以及activeMQ源码扩展中有使用)

二 原理剖析

并发编程网上有一篇极其优秀的译文(如果学习Diruptor必看),是针对Disruptor官方发布文章的译文 http://ifeve.com/disruptor/ ,从代码的实现以及优化的功能点中去讲诉为什么Disruptor很快,以及讲诉了Disruptor框架中重要的数据传递的buffer:RingBuffer ,以及LMAX架构
在这里插入图片描述
看了之后,不明觉得这个作者真的好牛逼,而且他的代码对于CPU的缓存行的性能优化,使用了缓存行填充的技术,就比如RingBuffer源码中会存在如下的代码
在这里插入图片描述
实际上p1,p7在源码中并没有使用,就是为了缓存行填充,(貌似distruptor3.2.2以上的版本才使用了这个)

cache line padding(缓存行填充):http://ifeve.com/disruptor-cacheline-padding/
memory barriers(内存屏障):http://ifeve.com/disruptor-memory-barrier/(这个类型jdk中volatile关键字的使用)

三 代码

原生的API代码:

/**
 *  <dependency>
        <groupId>com.lmax</groupId>
        <artifactId>disruptor</artifactId>
        <version>3.2.1</version>
    </dependency>
 *  Disruptor是一个高性能的异步处理框架,或者可以认为是线程间通信的高效低延时的内存消息组件,
 *  它最大特点是高性能,其LMAX架构可以获得每秒6百万订单,用1微秒的延迟获得吞吐量为100K+。
 *
 *
 *  使用原生的API创建一个简单的生产者和消费者数据
 *
 *
 * @author: zhoucg
 * @date: 2019-06-25
 */
public class DisruptorDemo {


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        int BUFFER_SIZE=1024;
        int THREAD_NUMBERS=4;
        //创建RingBuffer
        final RingBuffer<TradeTransaction> ringBuffer = RingBuffer.createSingleProducer(() -> new TradeTransaction(),BUFFER_SIZE,new YieldingWaitStrategy());
        //创建线程池
        ExecutorService executors = Executors.newFixedThreadPool(THREAD_NUMBERS);
        //创建SequenceBarrier
        SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();
        //创建消息处理器
        BatchEventProcessor<TradeTransaction> transProcessor = new BatchEventProcessor<>(ringBuffer,sequenceBarrier,new TradeTransactionInDBHandler());
        //处理
        executors.submit(transProcessor);

        //创建一个消费者
        Future<?> future=executors.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                long seq;
                for(int i=0;i<1000;i++){
                    seq=ringBuffer.next();//占个坑 --ringBuffer一个可用区块
                    ringBuffer.get(seq).setPrice(Math.random()*9999);//给这个区块放入 数据  如果此处不理解,想想RingBuffer的结构图
                    ringBuffer.get(seq).setId(UUID.randomUUID().toString()+"===="+i); //
                    ringBuffer.publish(seq);//发布这个区块的数据使handler(consumer)可见
                }
                return null;
            }
        });
        future.get();//等待生产者结束
        Thread.sleep(1000);//等上1秒,等消费都处理完成
        transProcessor.halt();//通知事件(或者说消息)处理器 可以结束了(并不是马上结束!!!)
        executors.shutdown();//终止线程

    }
}

使用WorkPool创建多个消费者

/**
 * 使用WorkerPool创建多个消费群
 * @author: zhoucg
 * @date: 2019-06-26
 */
public class DisruptorWorkerPoolDemo {

    public static void main(String[] args) throws InterruptedException {
        int BUFFER_SIZE=1024;
        int THREAD_NUMBERS=4;

        final RingBuffer<TradeTransaction> ringBuffer = RingBuffer.createSingleProducer(() -> new TradeTransaction(),BUFFER_SIZE,new YieldingWaitStrategy());

        SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUMBERS);

        //创建两个消费者,实现至WorkHandler
        WorkHandler<TradeTransaction> workHandlers = event -> System.out.println(Thread.currentThread().getName()+":"+event.getId());
        WorkHandler<TradeTransaction> workHandlers2 = event -> System.out.println(Thread.currentThread().getName()+":"+event.getId());


        //创建一个消费池
        WorkerPool<TradeTransaction> workerPool=new WorkerPool(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), workHandlers,workHandlers2);
        workerPool.start(executor);

        //下面模拟生产数据
        for(int i=0;i<8;i++){
            long seq=ringBuffer.next();
            ringBuffer.get(seq).setPrice(Math.random()*9999);
            ringBuffer.get(seq).setId(UUID.randomUUID().toString()+"="+i);
            ringBuffer.publish(seq);
        }

        Thread.sleep(1000);
        workerPool.halt();
        executor.shutdown();


    }
}

使用Disruptor创建多个消费者,多个生产者

/**
 * @author: zhoucg
 * @date: 2019-06-26
 */
public class Demo3 {

    public static void main(String[] args) throws InterruptedException {
        long beginTime=System.currentTimeMillis();
        int bufferSize=1024;
        ExecutorService executor= Executors.newFixedThreadPool(8);
        Disruptor<TradeTransaction> disruptor=new Disruptor<TradeTransaction>(() -> new TradeTransaction(), bufferSize, executor, ProducerType.SINGLE, new BusySpinWaitStrategy());
        //使用disruptor创建消费者组C1,C2
        //TradeTransactionVasConsumer实现EventHandler,EventHandler是能够对于event时间处理的过程进行感知
        EventHandlerGroup<TradeTransaction> handlerGroup=disruptor.handleEventsWith(new TradeTransactionVasConsumer(),new TradeTransactionInDBHandler());
        TradeTransactionJMSNotifyHandler jmsConsumer=new TradeTransactionJMSNotifyHandler();
        //声明在C1,C2完事之后执行JMS消息发送操作 也就是流程走到C3
        handlerGroup.then(jmsConsumer);


        disruptor.start();//启动
        CountDownLatch latch=new CountDownLatch(1);
        //生产者准备
        executor.submit(new TradeTransactionPublisher(latch, disruptor));
        latch.await();//等待生产者完事.
        disruptor.shutdown();
        executor.shutdown();

        System.out.println("总耗时:"+(System.currentTimeMillis()-beginTime) / 1000);
    }

    static class TradeTransactionPublisher implements Runnable{
        Disruptor<TradeTransaction> disruptor;
        private CountDownLatch latch;

        private static int LOOP=10000000;//模拟一千万次交易的发生

        public TradeTransactionPublisher(CountDownLatch latch,Disruptor<TradeTransaction> disruptor) {
            this.disruptor=disruptor;
            this.latch=latch;
        }

        @Override
        public void run() {
            TradeTransactionEventTranslator tradeTransloator=new TradeTransactionEventTranslator();
            for(int i=0;i<LOOP;i++){
                disruptor.publishEvent(tradeTransloator);
            }
            latch.countDown();
        }
    }

    static class TradeTransactionEventTranslator implements EventTranslator<TradeTransaction> {
        private Random random=new Random();

        @Override
        public void translateTo(TradeTransaction event, long sequence) {
            this.generateTradeTransaction(event);
        }

        private TradeTransaction generateTradeTransaction(TradeTransaction trade){
            trade.setId(UUID.randomUUID().toString());
            trade.setPrice(random.nextDouble()*9999);
            return trade;
        }

    }
}

代码地址: https://github.com/zcswl7961/javaProject_demo/tree/develop/src/main/java/com/common/util/disruptor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值