原文地址:http://mechanitis.blogspot.com/2011/07/dissecting-disruptor-wiring-up.html (因被墙移到墙内)

So now I’ve covered the ring buffer itself, reading from it and writing to it.

Logically the next thing to do is to wire everything up together.

I talked about multiple producers – they have the producer barrier to keep them in order and under control.  I’ve talked about consumers in a simple situation.  Multiple consumers can get a little more involved.  We’ve done some clever stuff to allow the consumers to be dependent on each other and the ring buffer.  Like a lot of applications, we have a pipeline of things that need to happen before we can actually get on with the business logic – for example, we need to make sure the messages have been journalled to disk before we can do anything.

The Disruptor paper and the performance tests cover some basic configurations that you might want. I’m going to go over the most interesting one, mostly because I needed the practice with the graphics tablet.

Diamond configuration
DiamondPath1P3CPerfTest illustrates a configuration which is not too uncommon – a single producer with three consumers.  The tricky point being that the third consumer is dependent upon the previous two consumers to finish before it can do anything.

Consumer three might be your business logic, consumer one could be backing up the data received, and consumer two may be preparing the data or something.

Diamond configuration using queues
In a SEDA-style architecture, each stage will be separated by a queue:

(Why does queue have to have so many “e”s?  It’s the letter I have the most trouble with in these drawings).

You might get an inkling of the problem here: for a message to get from P1 to C3 it has to travel through four whole queues, each queue taking its cost in terms of putting the message on the queue and taking it off again.

Diamond configuration using the Disruptor
In the Disruptor world, it’s all managed on a single ring buffer:

It does look more complicated.  But the ring buffer remains the single point of contact between all the players, and the interactions are all based on the barriers checking the sequence numbers of the things it’s dependent upon.

The producer side is fairly simple, it’s the single producer model described in my last post. Interestingly, the producer barrier doesn’t have to care about all the consumers.  It only cares about consumer three, because if consumer three has finished with an item in the ring buffer the other two will already have processed it.  So if C3 has moved on, that slot in the ring buffer is available.

To manage the dependencies between the consumers you need two consumer barriers.  The first just talks to the ring buffer and consumers one and two ask it for the next available item.  The second consumer barrier knows about consumers one and two, and it will return the lowest sequence number processed by both consumers.

How consumer dependencies work in the Disruptor
Hmm.  I can see I’m going to need an example.

We’re joining the party halfway through the story: the producer has filled the ring buffer up to sequence number 22; consumer one has read and processed everything up to 21; consumer two has processed everything up to sequence 18; consumer three, which is dependent upon the other consumers, has only made it as far as 15.

The producer can’t write anything more to the ring buffer because sequence 15 is taking up the slot where we’d want to put sequence 23.

(I’m sorry, I really did try to find an alternative to red and green, but everything else was just as ambiguous).

The first consumer barrier lets consumers one and two know they can grab anything up to sequence 22, the highest sequence number in the ring buffer.  The second consumer barrier checks the ring buffer sequence, but it also checks the sequences on the other two consumers and returns the lowest value.  So consumer three is told it can get anything up to sequence 18 from the ring buffer.

Note that the consumers are still reading the entries directly from the ring buffer – consumers one and two are not taking the entries off the ring buffer and then passing them on to consumer three.  Instead, the second consumer barrier is letting consumer three know which entry in the ring buffer it’s safe to process.

This raises a question – if everything comes directly off the ring buffer, how is consumer three going to find out about anything the first two consumers have done?  If all consumer three cares about is that the earlier consumers have done their job (e.g. replicating the data to somewhere else) then everything’s fine – when consumer three is told the job is done, it’s happy.  If, however, consumer three needs the results of an earlier consumer’s processing, where does it get that from?

Modifying entries
The secret is to write them to the ring buffer Entry itself.  This way, when consumer three grabs the entry off the ring buffer, it will have

been populated with all the information consumer three needs to do the job.  The really important part of this is that for each field on the Entry only one consumer is allowed to write to it.  This prevents any write-contention which will slow the whole thing down.

You can see this in DiamondPath1P3CPerfTest – FizzBuzzEntry has two fields as well as the value:fizz and buzz.  If the consumer is a Fizz consumer, it writes to fizz.  If it’s a Buzz consumer, it writes to buzz.  The third consumer, FizzBuzz, will read both of these fields but not write to either, since reading is fine and won’t cause contention.

Some actual Java code
All this looks more complicated than the queue implementation.  And yes, it does involve a bit more coordination.  But this is hidden from the consumers and producers, they just talk to the barriers.  The trick is in the configuration.  The diamond graph in the example above would be created using something like the following:

ConsumerBarrier consumerBarrier1 = ringBuffer.createConsumerBarrier();BatchConsumer consumer1 = new BatchConsumer(consumerBarrier1, handler1);
BatchConsumer consumer2 = new BatchConsumer(consumerBarrier1, handler2);ConsumerBarrier consumerBarrier2 = ringBuffer.createConsumerBarrier(consumer1, consumer2);BatchConsumer consumer3 = new BatchConsumer(consumerBarrier2, handler3);ProducerBarrier producerBarrier = ringBuffer.createProducerBarrier(consumer3);

In summary
So there you have it – how to wire up the Disruptor with multiple consumers that are dependent on each other.  The key points:

  • Use multiple consumer barriers to manage dependencies between consumers.
  • Have the producer barrier watch the last consumer in the graph.
  • Allow only one consumer to write to an individual field in an Entry.

EDIT: Adrian has written a nice DSL to make wiring up the Disruptor much easier.

EDIT 2: Note that version 2.0 of the Disruptor uses different names to the ones in this article.  Please see my summary of the changes if you are confused about class names.  Also Adrian’s DSL is now part of the main Disruptor code base.

dissecting-disruptor-wiring-up相关推荐

  1. 征集并发文献译者之Disruptor

    为了促进并发编程在中国的推广和研究,让更多的同学能阅读到国外的并发文献.所以打算将国外的并发编程文献翻译成中文,但是我一个人的精力有限,所以希望征集译者帮忙一起翻译.本期主要翻译Disruptor. ...

  2. Dissecting BERT Part 1: The Encoder 解析BERT解码器(transformer)

    原文:https://medium.com/dissecting-bert/dissecting-bert-part-1-d3c3d495cdb3 A meaningful representatio ...

  3. 你需要知道的高性能并发框架Disruptor原理

    Disruptor的小史 现在要是不知道Disruptor真的已经很outer了,Disruptor是英国外汇交易公司LMAX开发的一款开源的高性能队列,LMAX Disruptor是一个高性能的线程 ...

  4. 小编带你进入强如 Disruptor 也发生内存溢出?

    前言 OutOfMemoryError 问题相信很多朋友都遇到过,相对于常见的业务异常(数组越界.空指针等)来说这类问题是很难定位和解决的. 本文以最近碰到的一次线上内存溢出的定位.解决问题的方式展开 ...

  5. 浅谈Disruptor

    Disruptor是一个低延迟(low-latency),高吞吐量(high-throughput)的事件发布订阅框架.通过Disruptor,可以在一个JVM中发布事件,和订阅事件.相对于Java中 ...

  6. 太牛逼了!项目中用了Disruptor之后,性能提升了2.5倍

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! ‍存储设备往往是速度越快价格越昂贵,速度越快价格越低廉.在 ...

  7. 你应该知道的高性能无锁队列Disruptor

    1.何为队列 听到队列相信大家对其并不陌生,在我们现实生活中队列随处可见,去超市结账,你会看见大家都会一排排的站得好好的,等待结账,为什么要站得一排排的,你想象一下大家都没有素质,一窝蜂的上去结账,不 ...

  8. Disruptor官方文档实现

    获得Disruptor Disruptor是什么,我就不废话了,本文是对官方文档的实现,直接进入主题,要使用Disruptor可以通过Maven或者下载jar来安装Disruptor,只要把对应的ja ...

  9. Disruptor技术调研之配置参数一览

    为什么80%的码农都做不了架构师?>>>    1.单生产者和多生产者 One of the best ways to improve performance in concurre ...

  10. disruptor框架为什么不流行_Java并发编程框架Disruptor

    Disruptor是什么? Disruptor是一个高性能的异步处理框架,一个轻量级的JMS,和JDK中的BlockingQueue有相似处,但是它的处理速度非常快,获得2011年程序框架创新大奖,号 ...

最新文章

  1. debian10 dhcp简单配置
  2. 多级反馈队列调度算法描述
  3. 虚拟机克隆以后出现“需要整合虚拟机磁盘”的解决方法
  4. navicat远程连接mysql10060
  5. 微信好友数据打包下载--微信数据分析(二)
  6. C语言 泛型链表的实现
  7. 女性自我的迷宫:看EMI的人体自拍
  8. 某Q娱乐网emlog程序整站源码
  9. [置顶] 杂七杂八
  10. python统计各分数段人数并可根据选择绘制不同的图形_python习题整理
  11. ZStack实践汇 | 详解ZStack高级功能--裸金属服务部署实践
  12. vray渲染里服务器信息,Vray使用手册——设置V-Ray渲染服务器
  13. 什么是黑链?常见的黑链代码?
  14. 联想电脑如何进入BIOS的方法汇总
  15. Wordpress 网站搭建及性能监控方法详解!
  16. 红米k20适配android q,比谷歌还快,红米K20 PRO首发安卓Q稳定版,只有华为心里苦...
  17. python爬取淘宝数据魔方_淘宝数据魔方是什么(淘宝数据魔方技术架构解析)
  18. java-net-php-python-jspm新开路东总布小学编程类课程教学系统计算机毕业设计程序
  19. android 播放gif会闪,android 播放gif动图
  20. Eclipes下载安装

热门文章

  1. python量化交易入门教程_Python期货量化交易基础教程(9)
  2. 力扣刷题-专项突破-SQL入门
  3. Geekbench 5 for Mac(检测系统性能工具)
  4. 踏入社会需要懂得的道理
  5. 【Netscaler】1、Citrix Netscaler Gateway Server地址重定向经典配置
  6. js实现判断鼠标滚轮的上下滚动
  7. ai怎么画循环曲线_图标扁平人物插画怎么画?场景渐变人物生活圆形app图标平面插画背景AI矢量图案设计ui素材...
  8. 贼好玩!几行代码将童年游戏搬上屏幕!
  9. 透明表盘 指南针 app_指南:在Web设计中使用透明度(不透明度)
  10. 2021年育婴员(五级)报名考试及育婴员(五级)免费试题