Disruptor 高性能环形消息框架
官方文档:Disruptor
1. 简介
Disruptor是一个高性能的互进程(Inter-process)和多线程(Multi-threaded)消息处理库,由LMAX交易所开发,用于在Java虚拟机(JVM)上实现高性能的交换和处理数据。Disruptor的核心目标是提供一种低延迟、高吞吐量的解决方案。
一些关键特性:
-
Disruptor设计用来减少延迟,因为它避免了使用锁和线程间上下文切换,而是采用了一种基于缓存行(cache line)的设计理念。
-
通过使用无锁编程和环形缓冲区(Ring Buffer)来实现高效的数据交换,Disruptor能够达到纳秒级别的延迟。
-
Disruptor的API简洁,易于理解和使用,使得开发者可以快速地集成到现有的系统中。
-
它支持多种消息处理模式,包括单线程、多线程和多进程处理。
-
Disruptor基于事件驱动模型,可以处理事件的发布和订阅。
-
它保证了事件的顺序和一致性,这对于需要顺序处理的业务场景非常重要。
-
Disruptor可以轻松地扩展以适应不同的处理需求,无论是增加消费者数量还是处理不同类型的事件。
-
它提供了精细的内存管理策略,包括预分配内存和内存屏障(Memory Barriers)的使用,以确保数据的可见性和一致性。
Disruptor的工作流程大致如下:
-
生产者(Producer):向环形缓冲区发布事件。
-
消费者(Consumer):从环形缓冲区读取事件并处理。
-
环形缓冲区(Ring Buffer):一个固定大小的缓冲区,事件被顺序地写入,并且可以被多个消费者并发读取。
-
序列屏障(Sequence Barrier):用于同步生产者和消费者之间的进度,确保消费者不会读取到未完全写入的事件。
2. 比较
与Spring消息监听器、Redis发布/订阅、Guava的EventBus一样,提供生产消息与消费消息的能力,极大的解耦应用程序各模块。
| 特性/技术 | Disruptor | Redis发布订阅 | Guava EventBus | Spring消息监听器 |
| 设计目的 | 高性能、低延迟的消息处理 | 分布式消息传递 | 简化事件发布和订阅流程 | 与Spring框架集成的声明式事件处理 |
| 性能 | 极高,纳秒级延迟 | 较高,受网络延迟影响 | 适中,适用于中等负载 | 适中,依赖于Spring事件传播机制 |
| 可靠性 | 高,适合关键任务 | 较低,消息可能会丢失 | 适中,需要正确管理订阅和发布 | 高,Spring框架提供事务支持 |
| 易用性 | 低,需要深入了解并发编程 | 高,简单的发布订阅模型 | 高,直观的API和灵活的线程模型 | 高,Spring框架提供注解支持 |
| 分布式支持 | 否,仅限于单个JVM内部 | 是,支持跨多个节点和应用的消息传递 | 否,仅限于单个JVM内部 | 否,仅限于单个JVM内部(除非结合消息中间件) |
| 线程模型 | 无锁设计,多线程 | 多线程,基于发布订阅机制 | 支持同步和异步事件分发 | 支持同步和异步事件分发 |
| 适用场景 | 高性能计算,如金融交易系统 | 分布式系统的消息传递,如微服务架构 | 简单的事件驱动应用,需要灵活的事件处理 | 需要Spring框架支持的企业级应用 |
| 配置复杂度 | 高,需要配置事件、工厂和处理器 | 低,Redis简单配置即可使用 | 低,通过注解或API简单配置 | 低,Spring框架自动配置 |
| 社区和文档 | 活跃,由LMAX提供支持 | 非常活跃,Redis社区广泛支持 | 活跃,Guava库由Google维护 | 非常活跃,Spring社区广泛支持 |
| 扩展性 | 高,可以自定义事件和处理器 | 高,可以与其他Redis特性结合使用 | 高,可以自定义事件处理逻辑 | 高,可以自定义事件和监听器 |
| 持久性 | 否,内存中处理,不提供持久化 | 是,可以结合Redis持久化选项 | 否,内存中处理,不提供持久化 | 可以结合数据库事务管理持久化 |
3. 实例
3.1 添加依赖
<!-- disruptor-->
<dependency><groupId>com.lmax</groupId><artifactId>disruptor</artifactId><version>3.4.2</version>
</dependency>
3.2 消息实体
package org.example.event;public class TradeEvent {private long tradeId;private String symbol;private double price;private int volume;// Constructor, getters and setterspublic TradeEvent() {}public long getTradeId() {return tradeId;}public void setTradeId(long tradeId) {this.tradeId = tradeId;}public String getSymbol() {return symbol;}public void setSymbol(String symbol) {this.symbol = symbol;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public int getVolume() {return volume;}public void setVolume(int volume) {this.volume = volume;}
}
3.3 消息实体工厂
import com.lmax.disruptor.EventFactory;public class TradeEventFactory implements EventFactory<TradeEvent> {@Overridepublic TradeEvent newInstance() {return new TradeEvent();}
}
3.4 消息处理器
public class TradeEventHandler implements EventHandler<TradeEvent> {@Overridepublic void onEvent(TradeEvent event, long sequence, boolean endOfBatch) {System.out.println(String.format("Trade Event. ID: %d, Symbol: %s, Price: %.2f, Volume: %d",event.getTradeId(), event.getSymbol(), event.getPrice(), event.getVolume()));}
}
3.5 配置disruptor启动器
package org.example.config;import com.lmax.disruptor.dsl.Disruptor;
import org.example.event.TradeEvent;
import org.example.event.TradeEventFactory;
import org.example.event.TradeEventHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.Executor;
import java.util.concurrent.Executors;@Configuration
public class DisruptorConfig {@Beanpublic Disruptor<TradeEvent> disruptor() {int bufferSize = 1024;Executor executor = Executors.newCachedThreadPool();Disruptor<TradeEvent> disruptor = new Disruptor<>(new TradeEventFactory(), bufferSize, executor);disruptor.handleEventsWith(new TradeEventHandler());System.out.println("Disruptor created.");disruptor.start();return disruptor;}}
3.6 测试
curl --request POST \--url 'http://localhost:8080/trade?apipost_id=35ef4f1dbd9000' \--header 'Accept: */*' \--header 'Accept-Encoding: gzip, deflate, br' \--header 'Connection: keep-alive' \--header 'Content-Type: application/json' \--header 'User-Agent: PostmanRuntime-ApipostRuntime/1.1.0' \--data '{"tradeId":1111,"symbol":"测试标记","price":32.3,"volume":3
}'
控制台输出
Trade Event. ID: 1111, Symbol: 测试标记, Price: 32.30, Volume: 3
相关文章:
Disruptor 高性能环形消息框架
官方文档:Disruptor 1. 简介 Disruptor是一个高性能的互进程(Inter-process)和多线程(Multi-threaded)消息处理库,由LMAX交易所开发,用于在Java虚拟机(JVM)上实现高性能…...
Python列表(二)
方式三: 创建对应的枚举对象 概念:通过枚举函数,生成一个新的对象 作用:函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列 同时列出数据下标和数据 #生成枚举对象 values [&…...
计算机网络:应用层 —— 网络应用模式
文章目录 客户—服务器方式和对等方式客户/服务器方式 (C/S方式)工作流程特点 对等方式 (P2P方式)工作流程P2P 应用特点 客户—服务器方式和对等方式 网络应用程序运行在处于网络边缘的不同的端系统上,通过彼此间的通信来共同完成某项任务。 开发一种新的网络应用…...
@Repository注解和@mapper的区别
1. Repository 注解 通俗解释: 你可以把 Repository 注解想象成是一个专门负责管理数据库操作的 “仓库管理员”。这个管理员主要负责和数据库打交道,就像管理一个大仓库一样,他会进行各种操作,比如把货物(数据&#x…...
解锁成长密码:探寻刻意练习之道
刻意练习,真有那么神? 在生活中,你是否有过这样的困惑:每天苦练英语口语,可一到交流时还是支支吾吾;埋头苦学吉他,却总是卡在几个和弦转换上;工作多年,业务能力却似乎陷入…...
cuda-cuDnn
cuda sudo /bin/sh cuda_11.7.0_515.43.04_linux.run cudnn cuDNN Archive | NVIDIA Developer Linux 系统 CUDA 多版本共存以及切换 – 颢天 安装cuda # 如果已经安装过驱动,驱动不需要再安装,取消勾选 安装cuDNN,cuda-cuDNN对应关系见…...
如何使用Python和PIL库生成带竖排文字的封面图像
在今天的博客中,我们将学习如何使用Python和PIL(Pillow)库生成一个简单而有创意的封面图像。我们将创建一个背景图像,并在其上绘制带有竖排文字的标题和副标题,最后再添加一些装饰性元素如星星和萤火虫。这个教程适合初…...
低代码开发 实战转型案例一览
数字浪潮澎湃,企业应用开发需求呈井喷之势。传统全栈开发虽底蕴深厚,然其漫长周期与高昂成本,难以追赶市场快速交付的急切步伐。无代码与低代码平台顺势崛起,宛如暗夜明灯,吸引非技术人员纷至沓来,投身应用…...
SQL Server中FIRST_VALUE和 LAST_VALUE窗口函数允许在一个指定的窗口内返回第一个或最后一个值
在 SQL Server 中,FIRST_VALUE 和 LAST_VALUE 是用于窗口函数(Window Functions)的两个非常有用的函数。它们允许你在一个指定的窗口内返回第一个或最后一个值。这两个函数通常与 OVER 子句一起使用,以定义窗口的范围和排序规则。…...
机器学习-高斯混合模型
文章目录 高斯混合模型对无标签的数据集:使用高斯混合模型进行聚类对有标签的数据集:使用高斯混合模型进行分类总结 高斯混合模型 对无标签的数据集:使用高斯混合模型进行聚类 对有标签的数据集:使用高斯混合模型进行分类 总结...
微信V3支付报错 平台证书及平台证书序列号
1.平台证书及平台证书序列号设置错误报错: 错误1: Verify the response’s data with: timestamp1735184656, noncea5806b8cabc923299f8db1a174f3a4d0, signatureFZ5FgD/jtt4J99GKssKWKA/0buBSOAbWcu6H52l2UqqaJKvrsNxvodB569ZFz5G3fbassOQcSh5BFq6hvE…...
41.欠采样技术下变频不能用与跨两个nyquist的情况下
当接收到的信号位于同一nyquist区间时,信号被成功的折叠到了第一Nyquist区间中。 当接收信号位于两个或多个采样区间时,最后多个区间的信号都会被折叠到第一Nyquist区间中造成信号的重叠。...
20241227通过配置nomodeset参数解决更新grub之后,ubuntu20.04.5无法启动的问题
20241227通过配置nomodeset参数解决更新grub之后,ubuntu20.04.5无法启动的问题 2024/12/27 17:34 0.397475]pci0000:00:07.0:DPC:RPPI0 l0gsize 0 is invalid dev/nvmeon1p9:clean,251849/4276224 files,3266309/17089792 blocks 缘起:公司电脑要安装加密…...
从 GitLab.com 到 JihuLab.com 的迁移指南
本文分享从 GitLab.com 到 JihuLab.com 的迁移指南。 近期,GitLab Inc. 针对其 SaaS 产品做了限制,如果被判定为国内用户,则会建议使用其在国内的发布版本极狐GitLab。从 GitLab SaaS 产品(GitLab.com)迁移到极狐GitL…...
深度学习中的并行策略概述:2 Data Parallelism
深度学习中的并行策略概述:2 Data Parallelism 数据并行(Data Parallelism)的核心在于将模型的数据处理过程并行化。具体来说,面对大规模数据批次时,将其拆分为较小的子批次,并在多个计算设备上同时进行处…...
Python大数据可视化:基于Python对B站热门视频的数据分析与研究_flask+hive+spider
开发语言:Python框架:flaskPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 管理员登录 管理员功能界面 排行榜界面 系统管理界面 看板展示 摘要 本项目以对B站热…...
利用 Python 编写一个 VIP 音乐下载脚本
在这篇博客中,我们将介绍如何使用 Python 编写一个简单的 VIP 音乐下载脚本,利用网页爬虫技术从一个音乐网站下载歌曲。通过解析网页,获取歌曲的真实下载链接,并将音乐文件保存到本地。我们将使用 requests 和 BeautifulSoup 库来实现这个过程。 目标 本脚本的主要功能是…...
linux内核如何实现TCP的?
TCP(传输控制协议)是网络通信中的核心协议之一,实现了可靠的、面向连接的、基于字节流的通信。在Linux内核中,TCP的实现相对复杂,涉及多个模块和层次。以下是一些关键概念和机制: 1. 协议栈 Linux 内核中的网络协议栈(Network Stack)是分层设计的,包括链路层、网络层…...
【Spring】基于XML的Spring容器配置——FactoryBean的使用
随着Spring框架应用程序的复杂性增加,开发者需要更加灵活和强大的工具来创建和管理Bean。FactoryBean是Spring提供的一种强大机制,它允许开发者自定义Bean的创建过程。这种机制不仅提高了Bean的创建灵活性,还可以简化复杂对象的构建过程。 在…...
Docker使用——国内Docker的安装办法
文章目录 参考资料前言Mac安装办法Homebrew 安装1. 直接下报错2. 安装homebrew, 用国内镜像3. 安装Docker4. 启动docker服务5. 测试是否安装成功 参考资料 鸣谢大佬文章。 macOS系统中:Docker的安装:https://blog.csdn.net/sulia1234567890…...
一天一个开源项目(第62篇):lark-cli - 飞书/Lark 官方 CLI 与 AI Agent Skills
引言 “Built for humans and AI Agents.” 这是「一天一个开源项目」系列的第 62 篇文章。今天介绍的项目是 lark-cli(GitHub)。 需要在终端或 AI 工作流里操作飞书/Lark?lark-cli 是 larksuite 团队维护的官方 CLI:11 个业务域…...
提示词合集【自用】
遇到什么问题 用什么方法解决的 为什么不用别的方法 还有没有更好的方法这是一个{简要描述},请根据以下方式,帮助我学习整个代码库: 项目结构 - 编译方式 - 入口 - 核心逻辑 - 时序图 - 各个步骤关键实现函数。 每次回复只聚焦其中一个部分&a…...
Open UI5 源代码解析之780:Label.js
源代码仓库: https://github.com/SAP/openui5 源代码位置:src\sap.m\src\sap\m\Label.js sap.m.Label 文件深度解析与项目作用说明 一、文件定位与整体职责 Label.js 位于 sap.m 组件库中,是一个非常基础却影响面极广的控件实现文件。它定义了 sap.m.Label 的完整行为,…...
论文AI率高不等于抄袭2026年高校政策盘点
论文AI率高,会不会被认定为学术不端?会不会影响毕业?和传统的"查重超标"性质一样吗? 这些问题在2026年毕业季被问得很多。这篇文章梳理清楚。 AI率高和抄袭:两件不同的事 先把概念说清楚: 传…...
Pixel Aurora Engine作品集:基于大气/明亮/交互哲学的100+原创像素图
Pixel Aurora Engine作品集:基于大气/明亮/交互哲学的100原创像素图 1. 像素极光引擎概览 Pixel Aurora Engine是一款专为像素艺术创作设计的AI绘图工作站。它采用复古游戏机风格的界面设计,将现代AI技术与经典8-bit美学完美融合。通过简单的文字描述&…...
10. Doris 系列第10篇:数据查询全攻略|Join/子查询/窗口函数,从基础到高级实战
适合人群:大数据开发、Doris查询调优工程师、数仓分析师、BI工程师核心价值:吃透Doris 2.x数据查询核心能力,掌握Join算法选型、子查询优化、多维聚合、窗口函数实战,解决查询慢、资源浪费、语法报错等问题系列说明:本…...
MFC界面现代化---自定义标题栏与控件美化实战
1. 为什么需要MFC界面现代化改造 很多老牌企业软件和工业控制系统都基于MFC框架开发,这些系统通常运行了十几年甚至更久。我接手过不少这类项目,最直观的感受就是界面实在太"复古"了——灰底蓝框的窗口、生硬的按钮、像素感明显的图标…...
快速使用 Docker 设置 Nexior AI 平台
Nexior 是一个开源项目,允许用户轻松部署自己的 AI 应用网站,功能包括 AI 问答、Midjourney 绘图、知识库问答、艺术二维码等。用户无需自己开发 AI 系统、购买 AI 账户或担心 API 支持和支付系统配置,提供零启动成本和无风险的方式通过 AI 获…...
Vivado IOBUF原语使用避坑:为什么你的双向端口信号总连不上?
Vivado IOBUF原语深度解析:从原理到实战的双向端口设计指南 在FPGA开发中,双向端口(inout)的设计一直是工程师们容易踩坑的领域。特别是当我们需要将独立的输入输出信号合并为顶层inout端口时,Vivado提供的IOBUF原语看…...
避开PSRR仿真三大坑:用Cadence psspxf分析分频器时,这些设置错了白忙活
避开PSRR仿真三大坑:用Cadence psspxf分析分频器时,这些设置错了白忙活 在模拟电路设计的精密世界里,电源抑制比(PSRR)仿真是评估电路抗干扰能力的关键环节。许多工程师在完成基础仿真流程后,常会遇到结果异…...
