Disruptor 全解析(2):如何从 Ring Buffer 读取?

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 原文地址:http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-how-do-i-read-from.html​​  作者是 Trisha Gee, LMAX 公司的一位女工程师。
原文地址: http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-how-do-i-read-from.html​​  作者是 Trisha Gee, LMAX 公司的一位女工程师。
 

这是理解 LMAX​ 开发的 Disruptor 模式​ 系列博客的下一篇。

 
从  上一篇博客​ 我们都明白了什么是 Ring Buffer 以及  它有多棒。遗憾的是,我还没有提到当你实际使用 Disruptor 时,怎样读写数据。
 

ConsumerBarrier 与消费者


这里我要稍微反过来介绍,因为总的来说这一段比较容易理解。假设一些魔法已经把数据填入 Ring Buffer 了,怎样从 Ring Buffer 读出这些数据?

Disruptor 全解析(2):如何从 Ring Buffer 读取?
(唔,我开始后悔使用 Paint/ Gimp​ 了。尽管这是个购买绘图板的好借口,如果我继续写下去的话... UML 界的权威们大概也在诅咒我的名字了。)
 
消费者(Consumer)是一个想从 Ring Buffer 里拿出数据的线程,它可以访问 ConsumerBarrier 对象——这个对象由 RingBuffer 创建并且代表消费者与它互动。就像 Ring Buffer 显然需要序号才能找到下一个可用节点一样,消费者一样需要知道序号——每个消费者都需要找到下一个它要访问的序号。在上面的例子中,消费者处理完了 Ring Buffer 里序号 8 之前的所有数据,那么它期待访问的下一个序号是 9。
 
消费者可以调用 ConsumerBarrier 对象的 waitFor() 方法,传递它需要的下一个序号:
 
    final long availableSeq = consumerBarrier.waitFor(nextSequence);
 
ConsumerBarrier 返回 RingBuffer 的最大可访问序号——在上面的例子中是 12。ConsumerBarrier 持有一个 WaitStrategy 值来决定它如何等待这个序号,我现在暂时不会描述它的细节,代码里已经概括了每一种 WaitStrategy 的优点和缺点 。
 
接下来怎么做?
 
接下来,消费者会一直逛来逛去,等待更多数据被写入 Ring Buffer。并且,写入数据后消费者会收到通知——节点 9,10,11 和 12 已写入。现在序号 12 到了,消费者可以指示 ConsumerBarrier 去拿这些序号里的数据了。
 
Disruptor 全解析(2):如何从 Ring Buffer 读取?
 
拿到了数据后,消费者会更新自己的游标 (cursor)。
 
你应该已经感觉得到,这样做是怎样有助于抹平延迟曲线尖峰了——代替逐个逐个节点的询问“我能拿下一个数据吗?现在怎么样了?现在呢?”,消费者 Consumer 只需要简单的说“当你拿到的数字比这个要大的时候请告诉我”,函数返回值会告诉它有多少个新的数据节点可以读取。因为这些新的节点的确已经写入(Ring Buffer 本身的序号已经更新),而且消费者对这些节点的唯一操作是读而不是写,因此访问不用加锁。这样简直太好了,不仅代码可以更加安全和简单,而且不用加锁的速度超快。
 
另一个额外的好处是——你可以用多个消费者 Consumer 读同一个 RingBuffer,  不需要加锁,也不需要用另外的队列来协调不同的线程。这样你可以在 Disruptor 的协调下实现真正的并发数据处理。
 
BatchConsumer​ 是一个消费端的例子代码。如果你实现了  BatchHandler​,  你可以用 BatchConsumer 来完成上面我提到的复杂工作。它很容易实现需要成批处理节点(例如上文 9-12 的节点)的功能而不用单独读取每一个节点。
 
更新:注意 Disruptor 2.0 版使用了与本文不一样的命名。如果你对类名感到困惑,请阅读我的  变更总结​。
目录
相关文章
|
Java
Disruptor 全解析(7):解密内存屏障(Memory Barrier)
原文地址:http://mechanitis.blogspot.com/2011/08/dissecting-disruptor-why-its-so-fast.html​​, 作者是 Trisha Gee, LMAX 公司的一位女工程师。
2541 0
|
Java
Disruptor 全解析(6):为什么它这么快 (二) - 神奇的 cacheline 补齐
原文地址:http://mechanitis.blogspot.com/2011/07/dissecting-disruptor-why-its-so-fast_22.html​, 作者是 Trisha Gee, LMAX 公司的一位女工程师。
1216 0
|
Java
Disruptor 全解析(5):为什么它这么快 (一) - Locks Are Bad
原文地址: http://mechanitis.blogspot.com/2011/07/dissecting-disruptor-why-its-so-fast.html​​,作者是 Trisha Gee, LMAX 公司的一位女工程师。
1199 0
|
Java
Disruptor 全解析(1):Ring Buffer 有什么特别?
原文地址: http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html​  作者是 Trisha Gee, LMAX 公司的一位女工程师。
1765 0
|
Java
Disruptor 全解析(3):写入 Ring Buffer
原文地址:http://mechanitis.blogspot.com/2011/07/dissecting-disruptor-writing-to-ring.html​ 作者是 Trisha Gee, LMAX 公司的一位女工程师。
934 0
|
Java
Disruptor 全解析(4):依赖关系组装
原文地址:http://mechanitis.blogspot.com/2011/07/dissecting-disruptor-wiring-up.html​ 作者是 Trisha Gee, LMAX 公司的一位女工程师。
1027 0
|
29天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
67 2
|
2月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
75 0

推荐镜像

更多