Disruptor它是一个开源的并发框架,并获得2011 Duke’s 程序框架创新奖,能够在无锁的情况下实现网络的Queue并发操作。
介绍
Disruptor是一个高性能的异步处理框架,一个轻量级的JMS,和JDK中的BlockingQueue有相似处,但是它的处理速度非常快,获得2011年程序框架创新大奖,号称“一个线程一秒钟可以处理600W个订单”(这有点吓人吧),并且Disruptor不仅仅只有buffer,它提供的功能非常强大,比如它可以帮助我们轻松构建数据流处理(比如一个数据先交给A和B这2个消费者并行处理后再交给C处理,是不是有点想起storm这种流处理,实际上strom的底层就是应用了disruptor来实现worker内部threads的通信)。
核心概念
核心概念
在我们理解Disruptor如何工作之前,定义一些将在整个文档和代码中使用的术语是值得的。对于那些倾向于DDD的人来说,将其视为Disruptor域的普遍存在的语言。
Ring Buffer(环形缓冲区):
环形缓冲区通常被认为是Disruptor的主要方面,但从3.0开始,环形缓冲区仅负责存储和更新通过Disruptor的数据(事件)。对于一些高级用例,可以完全由用户替换。
Sequence:
Disruptor使用Sequences作为识别特定组件所在位置的方法。每个消费者(EventProcessor)都像Disruptor本身一样维护一个Sequence。大多数并发代码依赖于这些Sequence值的移动,因此Sequence支持AtomicLong的许多当前功能。事实上,两者之间唯一真正的区别是序列包含额外的功能,以防止序列和其他值之间的错误共享。
Sequencer:
Sequencer是Disruptor的真正核心。该接口的两个实现(单生成器,多生产者)实现了所有并发算法,用于在生产者和消费者之间快速,正确地传递数据。
Sequence Barrier:
序列屏障由序列发生器产生,包含对序列发生器中主要发布的序列和任何依赖性消费者的序列的引用。它包含确定是否有任何可供消费者处理的事件的逻辑。
Wait Strategy:
等待策略确定消费者如何等待生产者将事件放入Disruptor。有关可选锁定的部分中提供了更多详细信息。
Event:
从生产者传递给消费者的数据单位。事件没有特定的代码表示,因为它完全由用户定义。
EventProcessor:
用于处理来自Disruptor的事件的主事件循环,并具有消费者序列的所有权。有一个名为 BatchEventProcessor的表示,它包含事件循环的有效实现,并将回调到使用的提供的EventHandler接口实现。
EventHandler:
由用户实现并代表Disruptor的使用者的接口。
Producer:
这是调用Disruptor以将事件排入队列的用户代码。这个概念在代码中也没有表示。
无锁的机制
在生产者/消费者模式下,disruptor号称“无锁并行框架”(要知道BlockingQueue是利用了Lock锁机制来实现的),这是怎么做到的呢?下面我们来具体分析下:
一个生产者 + 一个消费者
生产者维护一个生产指针P,消费者维护一个消费者指针C,当然P和C本质上就是序号。2者各操作各的,不需要锁,仅仅需要注意的是生产者和消费者的速度问题,当然这个在disruptor内部已经为我们做了处理,就是判断一下P和C之间不能超过一圈的大小。
一个生产者 + 多个消费者
多个消费者当然持有多个消费指针C1,C2,…,消费者依据C进行各自读取数据,只需要保证生产者的速度“协调”最慢的消费者的速度,就是那个不能超出一圈的概念。此时也不需要进行锁定。
多个生产者 + N个消费者
很显然,无论生产者有几个,生产者指针P只能存在一个,否则数据就乱套了。那么多个生产者之间共享一个P指针,在disruptor中实际上是利用了CAS机制来保证多线程的数据安全,也没有使用到锁。
文档信息
- 本文作者:hsfeng
- 本文链接:https://hsfeng.site/hsfengbyte.github.io.old/2022/05/28/disruptor/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)