Disruptor是一个开源框架 , 研发的初衷是为了解决高并发下队列锁的问题 , 最早由LMAX提出并使用 , 能够在无锁的情况下实现队列的并发操作 , 并号称能够在一个线程里每秒处理6百万笔订单
官网:lmax-exchange.github.io/disruptor/
目前 , 包括Apache Storm、Camel、Log4j2在内的很多知名项目都应用了Disruptor以获取高性能
为什么会产生Disruptor框架「目前JAVA内置队列保证线程安全的方式:」
ArrayBlockingQueue:基于数组形式的队列 , 通过加锁的方式 , 来保证多线程情况下数据的安全;
LinkedBlockingQueue:基于链表形式的队列 , 也通过加锁的方式 , 来保证多线程情况下数据的安全;
ConcurrentLinkedQueue:基于链表形式的队列 , 通过CAS的方式
我们知道 , 在编程过程中 , 加锁通常会严重地影响性能 , 所以尽量用无锁方式 , 就产生了Disruptor这种无锁高并发框架
基本概念参考地址:github.com/LMAX-Exchan…
RingBuffer——Disruptor底层数据结构实现 , 核心类 , 是线程间交换数据的中转地;
Sequencer——序号管理器 , 生产同步的实现者 , 负责消费者/生产者各自序号、序号栅栏的管理和协调,Sequencer有单生产者,多生产者两种不同的模式,里面实现了各种同步的算法;
Sequence——序号 , 声明一个序号 , 用于跟踪ringbuffer中任务的变化和消费者的消费情况 , disruptor里面大部分的并发代码都是通过对Sequence的值同步修改实现的,而非锁,这是disruptor高性能的一个主要原因;
SequenceBarrier——序号栅栏 , 管理和协调生产者的游标序号和各个消费者的序号 , 确保生产者不会覆盖消费者未来得及处理的消息 , 确保存在依赖的消费者之间能够按照正确的顺序处理
EventProcessor——事件处理器 , 监听RingBuffer的事件 , 并消费可用事件 , 从RingBuffer读取的事件会交由实际的生产者实现类来消费;它会一直侦听下一个可用的序号 , 直到该序号对应的事件已经准备好 。
EventHandler——业务处理器 , 是实际消费者的接口 , 完成具体的业务逻辑实现 , 第三方实现该接口;代表着消费者 。
Producer——生产者接口 , 第三方线程充当该角色 , producer向RingBuffer写入事件 。
Wait Strategy:Wait Strategy决定了一个消费者怎么等待生产者将事件(Event)放入Disruptor中 。
文章插图
等待策略源码地址:github.com/LMAX-Exchan…
「BlockingWaitStrategy」
Disruptor的默认策略是BlockingWaitStrategy 。在BlockingWaitStrategy内部是使用锁和condition来控制线程的唤醒 。BlockingWaitStrategy是最低效的策略 , 但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现 。
「SleepingWaitStrategy」
SleepingWaitStrategy 的性能表现跟 BlockingWaitStrategy 差不多 , 对 CPU 的消耗也类似 , 但其对生产者线程的影响最小 , 通过使用LockSupport.parkNanos(1)来实现循环等待 。
「YieldingWaitStrategy」
YieldingWaitStrategy是可以使用在低延迟系统的策略之一 。YieldingWaitStrategy将自旋以等待序列增加到适当的值 。在循环体内 , 将调用Thread.yield()以允许其他排队的线程运行 。在要求极高性能且事件处理线数小于 CPU 逻辑核心数的场景中 , 推荐使用此策略;例如 , CPU开启超线程的特性 。
「BusySpinWaitStrategy」
性能最好 , 适合用于低延迟的系统 。在要求极高性能且事件处理线程数小于CPU逻辑核心数的场景中 , 推荐使用此策略;例如 , CPU开启超线程的特性 。
「PhasedBackoffWaitStrategy」
自旋 + yield + 自定义策略 , CPU资源紧缺 , 吞吐量和延迟并不重要的场景 。
使用举例参考地址:github.com/LMAX-Exchan…
<dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.3.4</version> </dependency>
//定义事件event 通过Disruptor 进行交换的数据类型 。public class LongEvent { private Long value; public Long getValue() { return value; } public void setValue(Long value) { this.value = value; }}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Tinyid 深度解密滴滴的高性能ID生成器
- Java 并发基础之内存模型
- 网络高并发
- 10大高性能开发宝石,我要消灭一半程序员
- Linux定时器 - 高性能定时器
- 抢鲜!阿里架构师私藏并发编程笔记,公开前半段秒获8K标星
- JAVA并发-AtomicInteger
- 如何进行Jmeter多接口指定TPS同时并发?
- 喝什么茶能提高性能力,喝什么茶能软化血管呢
- M.2接口SSD就是高性能存储的代名词?不同插槽代表不同速度