假如你生活在另外一个星球,我们最近开源了一套高性能的基于消息传递的开源框架。
下面我给大家介绍一下如何将消息通过Ring buffer在无锁的情况下进行处理。
在深入介绍之前,可以先快速阅读一下Trish发表的文章,该文章介绍了ring buffer和其工作原理。
这篇文章的要点如下:
1.ring buffer是由一个大数组组成的。
2.所有ring buffer的“指针”(也称为序列或游标)是java long类型的(64位有符号数),指针采用往上计数自增的方式。(不用担心越界,即使每秒1,000,000条消息,也要消耗300,000年才可以用完)。
3.对ring buffer中的指针进行按ring buffer的size取模找出数组的下标来定位入口(类似于HashMap的entry)。为了提高性能,我们通常将ring buffer的size大小设置成实际使用的2倍。
这样我们可以通过位运算(bit-mask )的方式计算出数组的下标。
Ring buffer的基础结构
注意:和代码中的实际实现,我这里描述的内容是进行了简化和抽象的。从概念上讲,我认为更加方面理解。
ring buffer维护两个指针,“next”和“cursor”。
在上面的图示里,是一个size为7的ring buffer(你应该知道这个手工绘制的图示的原理),从0-2的坐标位置是填充了数据的。
“next”指针指向第一个未填充数据的区块。“cursor”指针指向最后一个填充了数据的区块。在一个空闲的ring bufer中,它们是彼此紧邻的,如上图所示。
填充数据(Claiming a slot,获取区块)
Disruptor API 提供了事务操作的支持。当从ring buffer获取到区块,先是往区块中写入数据,然后再进行提交的操作。
假设有一个线程负责将字母“D”写进ring buffer中。将会从ring buffer中获取一个区块(slot),这个操作是一个基于CAS的“get-and-increment”操作,将“next”指针进行自增。这样,当前线程(我们可以叫做线程D)进行了get-and-increment操作后,
指向了位置4,然后返回3。这样,线程D就获得了位置3的操作权限。
接着,另一个线程E做类似以上的操作。
提交写入
以上,线程D和线程E都可以同时线程安全的往各自负责的区块(或位置,slots)写入数据。但是,我们可以讨论一下线程E先完成任务的场景…
线程E尝试提交写入数据。在一个繁忙的循环中有若干的CAS提交操作。线程E持有位置4,它将会做一个CAS的waiting操作,直到 “cursor”变成3,然后将“cursor”变成4。
再次强调,这是一个原子性的操作。因此,现在的ring buffer中,“cursor”现在是2,线程E将会进入长期等待并重试操作,直到 “cursor”变成3。
然后,线程D开始提交。线程E用CAS操作将“cursor”设置为3(线程E持有的区块位置)当且仅当“cursor”位置是2.“cursor”当前是2,所以CAS操作成功和提交也成功了。
这时候,“cursor”已经更新成3,然后所有和3相关的数据变成可读。
这是一个关键点。知道ring buffer填充了多少 – 即写了多少数据,那一个序列数写入最高等等,是游标的一些简单的功能。“next”指针是为了保证写入的事务特性。
最后的疑惑是线程E的写入可见,线程E一直重试,尝试将“cursor”从3更新成4,经过线程D操作后已经更新成3,那么下一次重试就可以成功了。
总结
写入数据可见的先后顺序是由线程所抢占的位置的先后顺序决定的,而不是由它的提交先后决定的。但你可以想象这些线程从网络层中获取消息,这是和消息按照时间到达的先后顺序是没什么不同的,而两个线程竞争获取一个不同循序的位置。
因此,这是一个简单而优雅的算法,写操作是原子的,事务性和无锁,即使有多个写入线程。
相关推荐
Disruptor是一个高性能的无锁并发框架,最初由LMAX开发。与传统的基于锁的并发模型相比,Disruptor通过创新的设计大幅提升了数据处理的效率和吞吐量。其核心特性包括环形数组结构、元素位置定位、无锁设计、和多种...
**Disruptor** 是一款高性能、低延迟的并发框架,它通过无锁设计实现了高效的队列操作,从而大大提升了多线程环境下的性能表现。该框架于2011年获得了Duke's Choice Award,这充分证明了其在并发处理领域的创新性和...
disruptor-3.4.2.jar 工具jar包 及 disruptor-3.4.2-sources.jar, Disruptor它是一个开源的并发框架,并获得2011 Duke’s 程序框架创新奖,能够在无锁的情况下实现网络的Queue并发操作,是 log4j2 引用的 jar 包
Disruptor是由LMAX公司开源的一款并发框架,其设计灵感来源于传统的消息队列,但通过独特的环形缓冲区(Ring Buffer)和事件处理机制,显著提升了并发性能,特别适用于高吞吐量、低延迟的场景。Disruptor的核心思想是...
基于Spring Boot和LMAX Disruptor的高性能并发框架 项目简介 本项目是一个基于Spring Boot和LMAX Disruptor框架的高性能并发框架,旨在提供高效的事件处理和消息传递机制。项目涵盖了并发编程的核心概念、无锁...
LMAX是一种新型零售金融交 易平台,它能够以很低的延迟产生大量交易。这个系统是建立在JVM平台上,其核心是一个业务逻辑处理 器,它能够在一个线程里每秒处理6百万订单。...业务逻辑处理器的核心是Disruptor。
《深入解析高并发框架Disruptor》 在现代互联网应用中,处理高并发场景是必不可少的技术挑战。Disruptor,由LMAX公司开发并开源,是一个高性能、低延迟的并发框架,尤其适用于需要大量数据交换的系统。本文将详细...
《Disruptor并发框架详解》 在高性能计算和并发编程领域,Disruptor是一个不可或缺的名字。这个由LMAX公司开发的并发框架,以其卓越的性能和低延迟特性,被广泛应用于金融交易、实时数据处理等领域。本文将深入探讨...
Disruptor是一个由LMAX公司开发的高性能并发框架,它的核心设计理念是采用无锁和零拷贝的技术,通过事件环形缓冲区来实现线程间的通信。在上述代码中,我们创建了一个Disruptor实例,定义了事件处理器DataConsumer,...
disruptor-3.3.11.jar 无锁并行框架 值得学习 jar包
Disruptor它是一个开源的并发框架能够在无锁的情况下实现网络的Queue并发操作。同时,Disruptor是一个高性能的异步处理框架,或者可以认为是最快的消息框架(轻量的JMS),也可以认为是一个观察者模式的实现,或者...
并发框架Disruptor介绍Martin Fowler在自己网站上写了一篇...下载剖析Disruptor为什么会这么快Disruptor如何工作和使用(五) Disruptor(无锁并发框架)-发布(六) LMAX Disruptor 一个高性能、低延迟且简单的框架(七) Di
- **无锁实现**:Disruptor使用了硬件级别的内存屏障来实现无锁算法,减少了线程间的同步开销。 - **批量处理**:通过批处理策略,多个事件可以一起处理,进一步提升效率。 - **消除不必要的对象创建**:...
Disruptor是一款高性能的Java并发框架,由LMAX公司开发并开源。它的设计目标是解决多线程环境下的数据同步问题,特别是在高并发场景下,能够显著提高系统的处理能力。Disruptor的核心设计理念是利用环形缓冲区(Ring...
disruptor-3.4.2.jar, 工具jar包, Disruptor它是一个开源的并发框架,并获得2011 Duke’s 程序框架创新奖,能够在无锁的情况下实现网络的Queue并发操作
Disruptor通过环形缓冲区、序列号、序列屏障、事件处理器和等待策略等关键组件实现了高效的无锁并发机制。开发者可以根据具体的应用需求选择合适的等待策略,从而在保证低延迟的同时,达到最优的性能表现。
Disruptor是由LMAX公司开发的一种高性能的并发编程框架,主要应用于金融交易系统。它以其高效、低延迟的事件处理机制而闻名。在C++版本的Disruptor中,我们同样可以享受到这种高效的并发能力,尤其适用于需要大量...
Disruptor 是一个高性能的并发编程框架,由 LMAX 公司开发,旨在解决线程间数据交换的效率问题。它的设计目标是替代传统的有界队列,提供更高的吞吐量和更低的延迟。Disruptor 的核心在于其创新的数据交换机制,包括...
Disruptor,由LMAX公司开源的一款并发框架,为处理高并发场景提供了一种新颖且高效的解决方案。它通过消除锁和线程间通信的开销,实现了微秒级的延迟和极高的吞吐量,尤其适用于金融交易、实时分析等对性能有苛刻...