LMAX-Exchange/disruptor-一个高性能、低延
简介
Disruptor它是一个开源的并发框架,并获得2011 Duke’s 程序框架创新奖,能够在无锁的情况下实现网络的Queue并发操作。
核心概念
在我们理解Disruptor怎么工作之前,很值得花一些时间理解几个 Disruptor 的核心概念。
-
Ring Buffer: 是Disruptor的核心概念,在3.0之后,他只负责存储和更新数据(event)。有一篇文章介绍的很详细,Ringbuffer的特别之处在于它是一种无锁数据结构,在操作它是免去了加锁、释放、等待的事件,所以性能出众。
-
Sequence: Disruptor使用 sequences代表一个特定的组件,每个消费者管理一个sequence。因此它有AutomicLong的很多特性,但是它会增加一些方法防止Sequence之间的错误分享。
-
Sequencer: 是一个核心组件。有两个实现,分别是single producer,multi producer。保证正确的producer 和 consumer之间正确的传递数据。
-
Wait Strategy: 决定了 consumer 是以什么方式等待,当 event 被 producer放入Disruptor的时候。
-
Event: producer传递给consumer的数据单元。event完全由用户定义。
-
EventHandler: 用户实现此接口,以实现 consumer的功能。
-
Producer: 用户代码调用Disruptor,吧Event放入队列。
下面这张图展示了 Disruptor 是如何工作的:
Paste_Image.png
Multicast Events
这是队列和Disruptor中间的最大的不同。当你在Disruptor注册了多个Consumer,event会发布给所有的consumer,然而队列只会发送给一个consumer。这个行为用在当你需要同一份数据并行两个不同的操作时。
看上图中,注册了三个EventHandler,每一个Handler都会接受到所有的消息,并且顺序一致。这可以实现操作的并行。
Event preallocation
Disruptor的一个目标是实现低延迟。为了实现低延迟,需要减少内存的申请,在java 中还要降低垃圾回收。
为了实现低延迟,Disruptor 会预先分配兑现个,并在运行过程中循环利用现有的对象。只要你正确实现了Disruptor的接口和方法,Disruptor保证这个操作时线程安全的。
Optionally Lock-free
为了实现低延迟的要求,另外一个关键实现引入Disruptor,那就是无锁编程算法。使用memory barriers和 compare-and-swap操作保证所有的内存的可见性和修正。只有一个用例实际上用到了锁,那就是BlockingWaitStrategy。
很多系统使用busy-wait实现低延迟。然而系统中的一些busy-wait会导致性能的显著下降,特别是CPU资源严重制约。如:虚拟环境的web服务。
参考
LMAX-Disruptor-learn(https://github.com/whyDK37/LMAX-Disruptor-learn)
LMAX Disruptor
剖析Disruptor:为什么会这么快?(一)Ringbuffer的特别之处
剖析Disruptor:为什么会这么快?(二)神奇的缓存行填充
剖析Disruptor:为什么会这么快?(三)揭秘内存屏障
Mechanical Sympathy
LMAX - How to Do 100K TPS at Less than 1ms Latency
False Sharing 伪共享