disruptor是一个高性能的本地消息队列,由于采用无锁实现,相比blockingQueue性能提升很多。在平时程序开发中,当需要异步实现时,disruptor是一个不错的选择。
如果仅仅只是了解如何使用是不够的,今天我们来了解一下disruptor的基本实现。
类图和作用
这里我们选取了BatchEventProcessor这个消费者来做说明,示例demo就不做展示,网上有很多。
这里有几个常用类的作用我们需要了解下:
- sequence: 如其名,包含一个long类型的value字段,用来跟踪当前生产者和消费者的进度位置。
- Sequencer: 用来生产sequence,在disrupor中有MultiProducerSequencer和SingleProducerSequencer两种序列号生产者实现。
- RingBuffer: disruptor的核心数据结构实现,为数据容器。
- EventHandler接口: 业务逻辑处理实现,用于我们实现自己的消费者业务逻辑。
- EventProcessor接口: disruptor系统内部的消费者实现,包装了EventHandler。
消费链实现
结合下面这段定义消费链的代码和上面的类图,我们了解下disruptor是如何实现链式消费的。
// 定义消费链,先并行处理日志、解码和复制,再处理结果上报
disruptor.handleEventsWith(new EventHandler[]{journalHandler,unmarshallHandler,replicateHandler}).then(resultHandler);
handleEventsWith方法的实现代码忽略。我们大致梳理下流程。
要实现resultHandler在前面3个Handler全部消费完后才执行,resultHandler必须要了解前面三个handler的处理进度。
在disruptor中,每一个Handler对一个包装对象BatchEventProcessor, 它里面包含一个sequenceBarrier, barrier这个对象中又包含了一个名为dependentSequence的Sequece。跟踪代码实现我们发现,在此hander前面没有依赖的消费者时,此sequence为cursor,即生产者最新生产的序列号,当有依赖的消费组时,则为FixedSequenceGroup,对应依赖的消费组的一组序列号。
到这里我们了解到,BatchEventProcessor通过barrier记录了前一组消费组的序列号,因此只需要判断自己本身获取的消费序列是否小于依赖组的序列号即可。