squencer 可简单理解为序号 waitStrategy 是一种策略等待
LMAX Disruptor,LMAX是一个新型的交易平台,号称能够单线程每秒处理数百万的订单 对高性能编程领域的一些传统观点,有点不对劲。这是一种更好、更快地在线程间共享数据的方法
从这个站点,你可以下载到一篇解释什么是Disruptor及它为什么如此高性能的文档
首先介绍ringbuffer。我对Disruptor的最初印象就是ringbuffer。但是后来我意识到尽管ringbuffer是整个模式(Disruptor)的核心,但是Disruptor对ringbuffer的访问控制策略才是真正的关键点所在。
正如名字所说的一样,它是一个环(首尾相接的环),可用做在不同线程间传递数据的buffer
RingBuffer
RingBuffer拥有一个序号,这个序号指向数组中下一个可用的元素
数组结构
如下图图片表示序号,这个序号指向数组的索引4的位置
随着不停地填充该buffer(可能也会有相应的读取),这个序号会一直增长,直到绕过这个环
要找到数组中当前序号指向的元素,可以通过mod操作
sequence mod array length = array index
以上面的RingBuffer为例(Java的mod语法):12 % 10 = 2 简单吧!
上图中的RingBuffer只有10个槽完全是个意外 如果槽的个数是2的N次方更有利于基于二进制的计算机进行计算
2的N次方换成二进制就是1000,100,10,1这样的数字 sequence & (array length-1) = array index 比如一共有8槽,3 &(8 -1)= 3,HashMap就是用这个方式来定位数组元素的,这种方式比取模的速度更快
如果你看了维基百科里面的关于环形buffer的词条,RingBuffer实现方式,与其最大的区别在于:没有尾指针
只维护了一个指向下一个可用位置的序号 选择用环形buffer的最初原因就是想要提供可靠的消息传递,需要将已经被服务发送过的消息保存起来,这样当另外一个服务通过nak (拒绝应答信号)告诉我们没有成功收到消息时,我们能够重新发送给他们
咋看,环形buffer非常适合这个场景。它维护了一个指向尾部的序号,当收到nak(校对注:拒绝应答信号)请求,可以重发从那一点到当前序号之间的所有消息:
ring buffer和常用的队列之间的区别是,不删除buffer中的数据,也就是说这些数据一直存放在buffer中,直到新的数据覆盖他们 这就是和维基百科版本相比,不需要尾指针的原因 ringbuffer本身并不控制是否需要重叠,决定是否重叠是生产者-消费者行为模式的一部分
ringbuffer采用这种数据结构,是因为它在可靠消息传递方面有很好的性能 这就够了,不过它还有一些其他的优点。