这是 Trisha Gee 发表的 Disruptor 全解析系列博客的后续补充,原文链接是:
http://mechanitis.blogspot.com/2011/08/disruptor-20-all-change-please.html
Martin 最近公布了
Disruptor 的
2.0 版本 —— 基本上,2.0 版自我们第一次开源以来有了如此多的改变,是需要把这些改变正式标记出来的时候了。Martin 的文章包含了所有的变化点,而我这一篇文章的目标是试图将之前的博客翻译成“新世界的语言”,因为把每篇博客都重写一遍得花很长时间。现在我知道用手工绘图表示一切的缺点了。
旧的世界
这是一个 Disruptor 消费结构的例子(具体来说,是菱形结构)。如果你对这个结构没有任何印象,可以随时退回去复习所有(但现在已经过时的)
Disruptor 细节。
过去几个星期最显而易见的变化是:
1. 更新了命名规则。
2. 把 ProducerBarrier 的功能集成到了 RingBuffer 里。
3. 添加了
DisruptorWizard 到主代码库。
新世界秩序
你可以看到(图中的)基本原理几乎是相同的。它更简单,因为 ProducerBarrier 本身不再是一个实体 —— 取代它的是 PublishPort 接口,它由 RingBuffer 对象自身所实现。
类似的,名称 DependencyBarrier 代替了 ConsumerBarrier 用以明确这个对象的职责;而 Publisher(代替 Producer)与 EventProcessor 代替 Consumer 也更准确的反映了它们在做什么。用 Consumer 做名称总会有一点点混淆,因为 Consumer 从来没有从 RingBuffer 真正消费过什么。它只是一个简单的术语,我们希望用它能给队列实现中那些常见的东西赋予意义。
没有在图中标明的是 RingBuffer 节点的名称变化 —— 在旧世界,我们称之为 Entry,现在它们叫 Event,因为在另一端的是 EventProcesser.
批量重命名的目的不是让我的旧博客变得毫无价值,这样我还可以周而复始的继续写 Disruptor 博客。这远远不是我想要的——我还有其他,更大的东西要写。重命名的目的是让 Disruptor 的工作原理和用法变得更容易理解。尽管
我们 只用 Disruptor 做消息处理,但是我们在开源时希望它看上去更像一个通用解决方案,因此试图在命名规则里体现这一点。但事实上,用消息处理模型看起来更加直观。
更简便的组装
现在
Disruptor Wizard 是 Disruptor 自身的一部分。我那一整篇
有关组装 的文章都变得没什么意义了 —— 这是好事,真的,因为它有一点涉及太多细节了。
如今,如果你要创建一个菱形消费模式(例如,
FuzzBuzz 性能测试那样的),代码会简单得多:
DisruptorWizard dw = new DisruptorWizard<FizzBuzzEvent>( ENTRY_FACTORY, RING_BUFFER_SIZE, EXECUTOR, ClaimStrategy.Option.SINGLE_THREADED, WaitStrategy.Option.YIELDING); FizzBuzzEventHandler fizzHandler = new FizzBuzzEventHandler(FIZZ); FizzBuzzEventHandler buzzHandler = new FizzBuzzEventHandler(BUZZ); FizzBuzzEventHandler fizzBuzzHandler = new FizzBuzzEventHandler(FIZZ_BUZZ); dw.handleEventsWith(fizzHandler, buzzHandler) .then(fizzBuzzHandler); RingBuffer ringBuffer = dw.start();
注意,这里是 Disruptor Wizard 的
Wiki 页面。
其他的改变:性能提升
就像 Martin 在
他的文章 中提到的那样,他在 2.0 版中设法显著的(甚至更多!)提升了 Disruptor 的性能。
这个消息的简短版本是增加了一个崭新的类,Sequence,同时兼顾
Cacheline Padding 和消除
Memory Barrier 的需求。现在的 Cacheline Padding 做法稍有不同,因为,Java7 做了件可爱的事情,它设法“优化”掉了我们使用的过时技术。
译注
我已经翻译了 Trisha Gee 的 Disruptor 全解析系列博客,下面是全部链接: