Ring Buffer的优势:
1. 内存屏障:volatile
提供与锁类似的语义,但是代码比锁小得多。volatile可以阻止代码重排序,并且值被更新的时候,会导致缓存失效,强制回写到主存中。
2. 伪共享与缓存行
CPU缓存通常一次缓存多个字(32、64或128字节),称为缓存行。如果位于同一个缓存行中的多个变量被不同的线程进行写,由于每次写都有可能刷新主存导致缓存失效,从而导致性能低下,即伪共享。可以使用缓存行填充来阻止共享缓存这种情况的出现,从而提升性能。如:
PaddedLong类,它使用了7个long,加上一个对象头,刚好64个字节。
Sequence类:private final long[] paddedValue = new long[15];
这个类更复杂一些,它的内存结构如下(从学习资料2中转载):
[头部: 8 bytes] 8
[数组长度: 4 bytes] 12
[padding: 4 bytes] 16
[元素1: 8 bytes] 24
[元素2: 8 bytes] 32
[元素3: 8 bytes] 40
[元素4: 8 bytes] 48
[元素5: 8 bytes] 56
[元素6: 8 bytes] 64
[元素7: 8 bytes] 72
[元素8: 8 bytes] 80
[元素9: 8 bytes] 88
[元素10: 8 bytes] 96
[元素11: 8 bytes] 104
[元素12: 8 bytes] 112
[元素13: 8 bytes] 120
[元素14: 8 bytes] 128
[元素15: 8 bytes] 136
Sequence使用了数组中第8个元素。这就意味着,无论在向头对齐还是向尾对齐,这个值总是会在一个单独的缓存行中。
有PaddedLong为什么还要Sequence类呢,主要是因为Java7对对象内存模型做了优化,如果它发现有字段没被使用,就会被优化掉,这时就又出现伪共享了。
见这篇博客:http://mechanical-sympathy.blogspot.com/2011/08/false-sharing-java-7.html
3. CAS:无锁更新
Compare and set,硬件直接支持的指令,ring buffer中通过UnSafe类来实现。
4. 大量的无锁实现(Sequence, PaddedLong等),使用数组存储数据(类似ArrayBlockingQueue),减少GC。
ring buffer整体结构:
一个环形的数组,next:下一个可用的slot。cursor:最近一个被填充的slot。
一个ClaimStrategy用于生产者生产数据时提供判断(当前是否有空闲的slot可以申请到),一个WaitStragety用于消费者消费数据时提供判断(当前是否有数据可以消费)。
其中ClaimStragety和WaitStragety都有针对不同场景的多种不同实现。
ClaimStragety:SingleThreadedClaimStragety,单线程;MultithreadedClaimStragety,多线程。
WaitStragety:
BlockingWaitStragety:使用了锁,实际上只能每个线程轮流来消费了。。。
BusySpinWaitStragety:使用自旋(会非常消耗CPU)
。。。
如何生产数据:
1. 取得当前可用的sequence
ringbuffer.next() ==> claimStragety.incrementAndGet() ==》waitForFreeSlotAt(依赖于消费者的sequence,即gatingSequences,每一个sequence都被一个BatchEventProcessor引用,代表最近消费的slot)。
看多个消费者中,消费得最慢的那个(即sequence最小的)如果minSequence > sequence-BufferSize,表示生产者和消费者重叠了,就需要等待。
2. 取得该sequence上的数据对象,填充对象
3. 发布数据。
claimStragety.serialisePublishing(sequence, cursor, batchSize);
waitStragety.signalAllWhenBlocking();
注意这里sequence是long的,cursor是Sequence类型的,位于Sequencer类中(RingBuffer的基类),是ring buffer维护的全局变量。
消费数据的时候,也不使用claimStragety。
生产者和消费者相对独立,只通过ring buffer来交互。这样相对地减少了耦合。
附几个disruptor的学习资料:
1. http://ifeve.com/disruptor/ 这是关于disruptor的入门文章。
2. http://www.dongsm.cn/disruptor%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90-%E5%8F%96%E6%A8%A1%E7%9A%84%E4%BC%98%E5%8C%96/ 这里关于disruptor写了一系列,相对还比较深入。