官方github
https://github.com/LMAX-Exchange/disruptor
几个重要概念
RingBuffer:环形的缓冲区,消息事件信息的载体。曾经 RingBuffer 是 Disruptor 中的最主要的对象,但从3.0版本开始,其职责被简化为仅仅负责对通过 Disruptor 进行交换的数据(事件)进行存储和更新。在一些更高级的应用场景中,Ring Buffer 可以由用户的自定义实现来完全替代。
Event:定义生产者和消费者之间进行交换的数据类型。
EventFactory:创建事件的工厂类接口,由用户实现,提供具体的事件
EventHandler:事件处理接口,由用户实现,用于处理事件
- ThreadFactory:这是一个线程工厂,用于我们Disruptor中生产者消费的时候需要的线程。
- EventTranslator:实现这个接口可以将我们的其他数据结构转换为在Disruptor中流通的Event。
应用场景
Disruptor是高性能的进程内线程间的数据交换框架,特别适合日志类的处理。
- 比如https://github.com/alipay/sofa-tracer,蚂蚁金服 团队开源的分布式链路追踪项目,其中日志处理部分就是使用了Disruptor。
- 包括Apache Storm、Camel、Log4j2等等知名的框架都在内部集成了Disruptor用来替代jdk的队列,以此来获得高性能。
疑问?
Disruptor可以动态增加消费者吗?
diruptor最优模型是生产者与消费者的关系是1:1,你可以让这一个消费者专门做分发dispatch,这样变成1:1:N,最后的N就是你需要的动态多个消费者,请注意,一旦让这个消费者做分发,效率性能就会降低。Disruptor单写原则的疑惑
单写原则适用于单机情况,并且只能启动一个服务实例,这种情况下的确可以做到单线程写入操作。
但是如果是集群的环境下,或者是单机启动多个服务实例,如何保证单写原则呢?
进一步考虑如果是集群环境下,领域模型的自身一致性规则(写入操作改变状态),是否也会冲突呢?
源码分析
待分析。。。。
三大特点
- CAS:利用CAS进行队列中的一些下标设置,减少了锁的冲突
- 消除伪共享:在Disruptor中采用了Padding的方式
- RingBuffer:采用了环形数组进行保存数据,Disruptor的特点是将多线程生产者通过Ringbuffer变成单线程消费者,通过单线程消费者对共享资源进行写操作
多个线程如果同时写同一个资源,必有争夺,就需要用锁或乐观锁等堵塞方法,而非堵塞的单线程写比多线程写要快,能获得高吞吐量和低延迟,特别是多核情况,一个线程一个CPU核,大大增加其他CPU核并行运行其他线程的概率。LMAX架构使用Disruptor每秒处理600万订单。
https://www.jdon.com/performance/singlewriter.html
告别Disruptor
一个简洁优雅的高性能并发队列
这个作者嫌Disruptor概念太复杂,而且性能也不高,自己写了一个高性能队列
文章地址:http://ifeve.com/%E5%91%8A%E5%88%ABdisruptor%E4%B8%80-%E7%AE%80%E6%B4%81%E4%BC%98%E9%9B%85%E7%9A%84%E9%AB%98%E6%80%A7%E8%83%BD%E5%B9%B6%E5%8F%91%E9%98%9F%E5%88%97/
github地址:https://github.com/Lofint/tachyon