一 简介
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