disruptor 无锁高效队列的使用
前言
使用队列在系统各阶段之间传递数据会引入延迟,因此我们重点优化该领域。Disruptor 是我们研究和测试的结果。我们发现 CPU 级别的缓存未命中以及需要内核仲裁的锁都非常昂贵,因此我们创建了一个对其运行的硬件具有“机械同情”的框架,并且该框架是无锁的。
官网: lmax-exchange.github.io/disruptor/
该框架架构图式:
简单阐述:
就是经典的生产者-消费者模型,在消息到的事件通知到绑定事件通知的接收者业务代码,去处理消息;
号称它的性能能达到每秒600百万,也是很多优秀开源框架的首选 消息消费模型的框架,目前Apache Storm、Camel、Log4j2在内的很多知名项目都在使用它;
简单使用
pom.xml
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.2</version>
</dependency>
//消息体
@Data
public class EventPaymentMessage {
private BlockingQueue<PaymentProductMessage> paymentProductMessageQueue;
}
@Data
@ToString
public class PaymentProductMessage {
/**
* 消息id
*/
private String msgId;
/**
* 流水号
*/
private Long flowNo;
/**
* 支付类型
*/
private Integer payTypeType;
/**
* 期待执行时间消息创建时间
*/
private Long expireTime;
}
// 消息事件工厂
public class OrderEventFactory implements EventFactory<EventPaymentMessage> {
@Override
public EventPaymentMessage newInstance() {
return new EventPaymentMessage();
}
}
//消息生产者
@Slf4j
public class OrderEventProducer {
//发布事件的buffer
private final RingBuffer<EventPaymentMessage> ringBuffer ;
public OrderEventProducer(RingBuffer<EventPaymentMessage> ringBuffer){
this.ringBuffer = ringBuffer;
}
//调用生产消息体
public void onData(BlockingQueue<PaymentProductMessage> paymentProductMessageQueue){
ArrayBlockingQueue<PaymentProductMessage> arrayBlockingQueue = new ArrayBlockingQueue<>(paymentProductMessageQueue.size());
for (PaymentProductMessage paymentProductMessage : paymentProductMessageQueue) {
try {
arrayBlockingQueue.put(paymentProductMessage);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
paymentProductMessageQueue=null;
//获取下个消息槽
long sequence = ringBuffer.next();
try {
//获取当前槽位消息 就是前面的EventFactory#newInstance方法生成新的消息
EventPaymentMessage eventPaymentMessage = ringBuffer.get(sequence); eventPaymentMessage.setPaymentProductMessageQueue(arrayBlockingQueue);
}finally {
//发布当前槽位下的消息
ringBuffer.publish(sequence);
}
}
@PostConstruct
private void init() {
//构建生产者的槽位大小和消息体
ringBuffer = RingBuffer.createSingleProducer(new OrderEventFactory(), BUFFER_SIZE);
//自定义的线程池用于生产者
ThreadPoolExecutor ringBufferPool = ThreadPoolConfig.RING_BUFFER_POOL;
//消费者
consumerEventHandles = new MultiConsumerEventHandle[CONSUMER_NUM];
//构建工作池
WorkerPool<EventPaymentMessage> workerPool = new WorkerPool<>(ringBuffer, ringBuffer.newBarrier(), new IgnoreExceptionHandler(), consumerEventHandles);
ringBuffer.addGatingSequences(workerPool.getWorkerSequences());
//工作在那个线程池
workerPool.start(ringBufferPool);
//生产者指定
producer = new OrderEventProducer(ringBuffer);
}
//生产者发送消息即可
log.info("生产者生成的消息为===>[{}]", paymentProductMessage);
producer.onData(nowDoQueue);
//消费者实现该类 消息下发到该方法
public interface WorkHandler<T>
{
/**
* Callback to indicate a unit of work needs to be processed.
*
* @param event published to the {@link RingBuffer}
* @throws Exception if the {@link WorkHandler} would like the exception handled further up the chain.
*/
void onEvent(T event) throws Exception;
}