Dissecting the Disruptor: How do I read from the ring buffer?

简介:

The next in the series of understanding the Disruptor pattern developed at LMAX.

After the last post we all understand ring buffers and how awesome they are.  Unfortunately for you, I have not said anything about how to actually populate them or read from them when you’re using the Disruptor.

ConsumerBarriers and Consumers
I’m going to approach this slightly backwards, because it’s probably easier to understand in the long run.  Assuming that some magic has populated it: how do you read something from the ring buffer?

(OK, I’m starting to regret using Paint/Gimp.  Although it’s an excellent excuse to purchase a graphics tablet if I do continue down this road.  Also UML gurus are probably cursing my name right now.)

Your Consumer is the thread that wants to get something off the buffer.  It has access to aConsumerBarrier, which is created by the RingBuffer and interacts with it on behalf of theConsumer.  While the ring buffer obviously needs a sequence number to figure out what the next available slot is, the consumer also needs to know which sequence number it’s up to – each consumer needs to be able to figure out which sequence number it’s expecting to see next.  So in the case above, the consumer has dealt with everything in the ring buffer up to and including 8, so it’s expecting to see 9 next.

The consumer calls waitFor on the ConsumerBarrier with the sequence number it wants next

    final long availableSeq = consumerBarrier.waitFor(nextSequence);

and the ConsumerBarrier returns the highest sequence number available in the ring buffer – in the example above, 12.  The ConsumerBarrier has a WaitStrategy which it uses to decide how to wait for this sequence number – I won’t go into details of that right now, the code has comments in outlining the advantages and disadvantages of each.

Now what?
So the consumer has been hanging around waiting for more stuff to get written to the ring buffer, and it’s been told what has been written – entries 9, 10, 11 and 12.  Now they’re there, the consumer can ask the ConsumerBarrier to fetch them.

As it’s fetching them, the Consumer is updating its own cursor.

You should start to get a feel for how this helps to smooth latency spikes – instead of asking “Can I have the next one yet?  How about now?  Now?” for every individual item, the Consumer simply says “Let me know when you’ve got more than this number”, and is told in return how many more entries it can grab.  Because these new entries have definitely been written (the ring buffer’s sequence has been updated), and because the only things trying to get to these entries can only read them and not write to them, this can be done without locks.  Which is nice.  Not only is it safer and easier to code against, it’s much faster not to use a lock.

And the added bonus – you can have multiple Consumers reading off the same RingBuffer, with no need for locks and no need for additional queues to coordinate between the different threads.  So you can really run your processing in parallel with the Disruptor coordinating the effort.

The BatchConsumer is an example of consumer code, and if you implement the BatchHandler you can get the BatchConsumer to do the heavy lifting I’ve outlined above.  Then it’s easy to deal with the whole batch of entries processed (e.g. from 9-12 above) without having to fetch each one individually.

EDIT: 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.


文章转自 并发编程网-ifeve.com

相关文章
|
消息中间件 存储 缓存
一文快速掌握高性能内存队列Disruptor
`Disruptor`是LMAX公司开源的高性能内存消息队列,单线程处理能力可达600w订单/秒。本文从使用和设计角度探讨这款Java消息队列。作者sharkChili是Java开发者,CSDN博客专家,Java Guide项目维护者。文章介绍了Disruptor的基础使用,包括前置步骤、消息模型、消息处理器配置、生产者实现,并展示了效果。同时,文章详细解析了Disruptor的工作流程和高效原因,如无锁操作、分支预测和缓存填充。最后,作者提供相关资源链接并邀请读者加入交流群。
4016 0
sql中的笛卡尔乘积问题
sql中的笛卡尔乘积问题
|
Linux 开发者 iOS开发
Python PIP
Python PIP
527 0
|
监控 Linux
Linux 进程标识符:深入探讨 getpid() 和 getppid()
在Linux操作系统中,进程管理是一项重要的任务。为了正确管理和监控进程,我们需要了解如何获取进程的标识符。本文将详细介绍两个重要的Linux系统调用函数:`getpid()`和`getppid()`。这两个函数用于获取当前进程的进程ID(PID)和父进程的PID。我们将深入探讨它们的用途、使用方法以及示例代码。
3682 0
|
开发框架 JavaScript 前端开发
Vue 3最新力作!《Vue.js 3企业级应用开发实战》简介
《Vue.js 3企业级应用开发实战》一书由电子工业出版社出版,已经于2022年1月出版上市。近日拿到了样书,第一时间希望与读者朋友们分享下这本书里面的内容。
1356 0
|
移动开发 JavaScript 前端开发
Vue.js 作者尤雨溪:直接学 Vue 3 吧
Vue.js 作者尤雨溪:直接学 Vue 3 吧
Vue.js 作者尤雨溪:直接学 Vue 3 吧
|
JavaScript 前端开发 测试技术
Angular 与 Node.js 无缝对接简直太牛啦!前后端分离最佳实践,开启高效开发新时代!
【8月更文挑战第31天】随着互联网技术的发展,前后端分离模式日益受到开发者青睐。本文综述了 Angular 与 Node.js 的优势及无缝对接技术,探讨了前后端分离的最佳实践。Angular 以其组件化开发、双向数据绑定等特性成为优秀的前端框架;Node.js 则依靠高并发处理能力和全栈 JavaScript 开发的优势在后端大放异彩。两者结合通过 HTTP 请求实现高效通信,并可通过数据库实现数据共享。此外,文章还强调了接口设计、代码分离、测试及部署等方面的最佳实践,为开发者提供了全面的指导。
749 0
|
缓存 资源调度 JavaScript
Nodejs 命令行调用 exec 与 spawn 差异--- 解决 spawn yarn ENOENT error
Nodejs 命令行调用 exec 与 spawn 差异--- 解决 spawn yarn ENOENT error

热门文章

最新文章