MongoDB实现发布订阅机制

一、MongoDB Pub/Sub 的实现原理
MongoDB 的发布订阅不是像 Redis 那样的原生 “频道式” Pub/Sub,而是基于变更流(Change Streams)(MongoDB 3.6+ 推荐)或早期的tailable cursor(可尾游标)实现:
Change Streams:监听集合 / 数据库 / 集群的实时数据变更(插入、更新、删除等),订阅者通过监听这些变更事件来接收 “消息”,发布者则通过向集合插入文档来 “发布消息”。
核心逻辑:把 “消息” 封装成文档插入 MongoDB 集合,订阅者监听该集合的插入事件,从而实现消息的发布与订阅。

const path = require('path'); const paths = require('../paths'); const dbManager = require(path.join(paths.manager, 'dbManager')) const COLLECTION_NAME = 'messages'; // 存储消息的集合名 // 并发 / 吞吐量能力(参考值,普通服务器硬件) // 指标 MongoDB(tailable cursor) Redis Pub/Sub MongoDB(Change Streams) // 单频道订阅者数量 支持 100+(无明显卡顿) 支持 1000+ 支持 50+ // 消息发布 QPS 1 万 - 5 万 / 秒 10 万 + / 秒 5000 - 2 万 / 秒 // 消息延迟(发布→接收) 1-10ms <1ms 5-20ms /** * 初始化:创建固定集合(仅需执行一次) * 固定集合是tailable cursor的前提,大小限制100MB,自动覆盖旧文档 */ async function initCappedCollection() { try { // 检查集合是否存在,不存在则创建固定集合 const collections = await dbManager.getDB().listCollections({ name: COLLECTION_NAME }).toArray(); if (collections.length === 0) { await dbManager.getDB().createCollection(COLLECTION_NAME, { capped: true, // 启用固定集合 size: 100 * 1024 * 1024, // 集合最大大小100MB max: 10000 // 最多存储10000条文档(二选一,满足其一即触发覆盖) }); console.log('固定集合创建成功'); } } catch (err) { console.error('初始化集合失败:', err); } } /** * 发布者:向集合插入消息文档(模拟发布) * @param {string} channel 频道名(区分不同类型的消息) * @param {any} data 要发布的消息内容 */ async function publish(channel, data) { try { const collection = dbManager.getDB().collection(COLLECTION_NAME); // 插入消息文档(包含频道、内容、时间戳) await collection.insertOne({ channel: channel, data: data, timestamp: new Date(), }); console.log(`[发布] 频道${channel}:`, data); } catch (err) { console.error('发布失败:', err); } } /** * 订阅者:监听指定频道的消息(模拟订阅) * @param {string} channel 要订阅的频道名 */ async function subscribe(channel) { try { const collection = dbManager.getDB().collection(COLLECTION_NAME); console.log(`[订阅] 开始监听频道${channel}...`); let lastId = null; const lastDoc = await collection.findOne( { channel: channel }, { sort: { $natural: -1 } } // 仅查询最后一条时用倒序,tailable cursor本身不用 ); if (lastDoc) { lastId = lastDoc._id; } // 创建tailable cursor(持续监听最新文档) const cursor = collection.find( lastId ? { channel: channel, _id: { $gt: lastId } } : { channel: channel }, // 只读新文档 { tailable: true, // 启用可尾游标 awaitData: true, // 等待新数据(阻塞查询) noCursorTimeout: true, // 禁用游标超时 sort: { $natural: 1 } // 仅支持正序 } ); // 持续遍历游标,接收新消息 while (true) { if (await cursor.hasNext()) { // 有新文档时触发 const message = await cursor.next(); console.log(`[接收] 频道${channel}:`, message.data); } else { // 无新数据时短暂等待,避免CPU空转 await new Promise(resolve => setTimeout(resolve, 100)); } } } catch (err) { console.error('订阅失败:', err); } } // -------------------------- 示例调用 -------------------------- async function runDemo() { await initCappedCollection() // 启动订阅者(监听"chat"频道) subscribe('chat'); // 延迟1秒后发布3条测试消息 setTimeout(() => publish('chat', { user: '张三', msg: '你好!' }), 1000); setTimeout(() => publish('chat', { user: '李四', msg: 'MongoDB Pub/Sub测试' }), 2000); setTimeout(() => publish('notice', { content: '这是通知频道,订阅者收不到' }), 3000); // 其他频道不接收 } module.exports = { runDemo, };

这个方案的性能消耗属于轻到中等级别,远低于 Redis Pub/Sub(Redis 是纯内存轻量级),但高于 MongoDB Change Streams(副本集模式),适合中小规模的消息场景(如单服务 / 低并发通知),不适合高并发、低延迟的核心业务场景。

1. CPU 消耗
客户端(Node.js 服务):
核心消耗点:cursor.hasNext() 循环 + 消息处理回调。
关键优化:开启 awaitData: true(代码中已配置)时,MongoDB 驱动会采用阻塞式 IO 等待新数据,而非空轮询,此时 CPU 占用极低(单订阅频道 CPU 使用率 < 1%);若关闭 awaitData 改用主动轮询(如每 100ms 查一次),CPU 会飙升至 10%+(空转消耗)。
多频道订阅:每增加一个频道,CPU 消耗线性增加,但单进程支持 50+ 频道订阅时,CPU 仍可控制在 5% 以内。
服务端(MongoDB):
固定集合(capped collection)的插入 / 查询都是顺序 IO(而非普通集合的随机 IO),CPU 消耗极低;
维护 tailable cursor 的开销可忽略(单节点下,100 个 cursor 仅占用 < 0.5 核 CPU)。
2. 内存消耗
客户端(Node.js 服务):
每个订阅频道对应一个 cursor 对象,内存占用仅几 KB;即使 100 个频道订阅,总内存增加也不足 1MB。
仅需缓存少量消息元数据(如最后一条消息的 _id),无额外内存压力。
服务端(MongoDB):
固定集合的元数据(索引、游标信息)占用内存约几十 MB;
固定集合本身会按 size 配置(如 100MB)加载部分数据到内存(MongoDB 缓存机制),但可通过 wiredTiger 缓存配置限制,避免内存溢出。
3. 磁盘 IO 消耗
固定集合是 MongoDB 中磁盘 IO 效率最高的集合类型:
插入消息时是顺序写(磁盘磁头无需频繁移动),比普通集合的随机写快 5-10 倍;
tailable cursor 读取消息是顺序读,几乎无随机 IO,磁盘 IO 利用率 > 90%;
对比普通集合:普通集合的随机写 IO 消耗是固定集合的 3-5 倍。
4. 网络消耗
连接层面:tailable cursor 会保持长连接(无频繁重连),无额外心跳包开销;
数据层面:仅传输新插入的消息数据(含 _id/channel/data/timestamp 等元数据),单条消息的网络包比 Redis Pub/Sub 大(Redis 仅传输纯消息内容,MongoDB 多文档元数据),但整体网络消耗仍属低级别;
并发订阅:多订阅者监听同一频道时,MongoDB 会为每个订阅者推送消息,网络消耗随订阅者数量线性增加(Redis 同理)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1206147.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

conda下安装cuda11.8和cudnn

当需要多个cuda版本的时候我们可以将cuda安装到虚拟机里。 conda install -c nvidia cuda-runtime11.8conda install -c nvidia cudnn

2026最新conda镜像源

设置miniconda镜像源vim ~/.condarc//替换下面的源channels:- defaults show_channel_urls: true default_channels:- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r- https://mirrors.tuna.tsinghua.edu.c…

GVHMR输出的.pt文件最全面分析

GVHMR / HMR4D 输出 .pt 文件规范化全量解读适用对象:GVHMR Demo 推理生成的结果文件(例如:hmr4d_results.pt) 目标:把字段结构、维度、语义、来源代码位置、关键公式、坐标系/骨架约定、后处理逻辑一次性讲清楚,…

《知行合一的价值革命:评〈AI元人文:悟空而行〉的思想、方法与伦理突破》

《知行合一的价值革命:评〈AI元人文:悟空而行〉的思想、方法与伦理突破》 引言 在人工智能治理领域,文本的丰裕与行动的贫困已构成一种时代性症候。《AI元人文:悟空而行——智能时代的价值决断与合法性重建》的出现…

【微服务注册与管理开源框架】从选型到实战(Nacos/Eureka/Consul/etcd/Zookeeper) - 实践

【微服务注册与管理开源框架】从选型到实战(Nacos/Eureka/Consul/etcd/Zookeeper) - 实践2026-01-23 18:33 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !importa…

高增长科技股投资法 核心内容深度拆解

高增长科技股投资法 核心内容深度拆解 最近读了《高增长科技股投资法》&#xff0c;我发现这个很不错&#xff0c;也很符合这次周期的内容。 于是用AI生成了一个概要记录&#xff0c;给朋友们分享一下做个参考。 有时间推荐去读一下原书&#xff0c;内容很有意思&#xff0c;可…

特殊符号绕过-ctfshow-web40

一、打开环境看源码if(isset($_GET[c])){$c $_GET[c];if(!preg_match("/[0-9]|\~|\|\|\#|\\$|\%|\^|\&|\*|\&#xff08;|\&#xff09;|\-|\|\|\{|\[|\]|\}|\:|\|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){eval($c);}}else{highlight_file(__FILE__); }…

国产Jira方案哪家强?2026年Jira替代工具测评指南

如果你正在做国产 Jira 方案与 Jira 替代工具选型&#xff0c;真正的难点从来不是有没有看板&#xff0c;而是能否承接你组织的流程、权限、数据与知识沉淀。本文测评 8 款工具&#xff1a;ONES、云效、华为云 CodeArts、CODING DevOps、TAPD、极狐GitLab、Gitee Issue、GitCod…

Halcon彩图阈值分割、腐蚀和膨胀、顶帽和底帽处理、求图像边界轮廓

*彩图阈值分割: •彩图转灰图:rgb1_to_gray () •从彩图当中提取3个通道的图像:decompose3 () •合并两个通道的算子:compose2() •合并三个通道的算子,又合并为之前的彩图:compose3() •获取图像是有几个通道组成的:count_channels () •通过索引值提取通道对应的图像:a…

Halcon图像滤波:均值滤波、中值滤波、高斯滤波、高通滤波、标准差滤波

*图像滤波:•滤波原理&#xff1a;图像滤波&#xff0c;即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制&#xff0c;是图像预处理中不可缺少的操作&#xff0c;其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。图像滤波的主要目的&#xff1a;为…

【必藏】零代码实现!告别AI幻觉,搭建专属知识库的RAG实战教程

本文介绍RAG(检索增强生成)技术如何解决大语言模型的局限性。RAG通过Embedding技术将问题转化为向量&#xff0c;在私有知识库中检索相关内容&#xff0c;然后结合参考资料生成回答&#xff0c;从根本上避免AI的"幻觉问题"。文章预告了下一篇实战教程&#xff0c;将指…

【强烈收藏】AI Agent全栈开发之路(15):RAG技术详解与向量模型实战

文章介绍AI Agent系列的第15篇内容&#xff0c;聚焦RAG&#xff08;检索增强生成&#xff09;技术。内容包括RAG概念、核心步骤&#xff08;文本向量化存储、检索、LLM生成&#xff09;、向量与向量化模型原理&#xff0c;以及使用阿里云通义API实现文本向量化的代码示例。RAG通…

【爆点实战】Spring AI电商客服RAG系统,双Advisor精准解答退换货、物流问题!代码收藏必学!

本文详细介绍了使用Spring AI构建电商客服智能知识库RAG系统的完整流程&#xff0c;包括需求分析、技术选型、环境配置、知识库构建、RAG核心配置及系统测试。系统支持PDF文档导入、Milvus向量存储&#xff0c;通过QuestionAnswerAdvisor和RetrievalAugmentationAdvisor两种检索…

云平台一键部署【Tencent-YouTu-Research/Youtu-LLM-2B】具备原生智能体能力

Youtu-LLM 是一款全新、小巧但功能强大的大语言模型&#xff08;LLM&#xff09;&#xff0c;仅包含 19.6 亿参数&#xff0c;支持 128k 长上下文&#xff0c;并具备原生的智能体&#xff08;agentic&#xff09;能力。在通用评估中&#xff0c;Youtu-LLM 在常识推理、STEM、编…

RAG系统效果差?真正决定成败的竟然是检索与生成之间的隐藏层!收藏这篇深度解析

本文揭示了RAG系统中常被忽视的关键环节——检索与生成之间的处理管道。研究发现大语言模型存在位置效应&#xff08;首因和近因效应&#xff09;&#xff0c;需将最相关文本块置于提示词前端。文章详细分析了重排序、去重、Token预算管理、提示词架构优化等关键技术&#xff0…

救命神器10个AI论文写作软件,本科生搞定毕业论文!

救命神器10个AI论文写作软件&#xff0c;本科生搞定毕业论文&#xff01; AI 工具&#xff0c;让论文写作不再难 对于大多数本科生来说&#xff0c;毕业论文不仅是学术生涯的一次重要考验&#xff0c;更是一场与时间、压力和焦虑的较量。面对庞大的文献资料、复杂的逻辑结构以及…

Java基于Spring Boot+Vue的走散儿童救助信息管理系统的设计与实现

所需该项目可以在最下面查看联系方式&#xff0c;为防止迷路可以收藏文章&#xff0c;以防后期找不到 这里写目录标题项目介绍系统实现截图技术栈介绍Spring Boot与Vue结合使用的优势Spring Boot的优点Vue的优点Spring Boot 框架结构解析Vue介绍系统执行流程Java语言介绍系统测…

Java基于Spring Boot+Vue的学生宿舍管理系统的设计于实现

所需该项目可以在最下面查看联系方式&#xff0c;为防止迷路可以收藏文章&#xff0c;以防后期找不到 这里写目录标题项目介绍系统实现截图技术栈介绍Spring Boot与Vue结合使用的优势Spring Boot的优点Vue的优点Spring Boot 框架结构解析Vue介绍系统执行流程Java语言介绍系统测…

2026年GEO优化服务商数据监测能力对比:谁才是真正的_数据驱动_?

在 GEO(生成式引擎优化)领域,“数据监测能力”是决定优化效果的第一生产力。本文基于“平台覆盖度、数据时效性、溯源精准度、白盒透明度”等 9 大关键指标,对主流 GEO 服务商的数据监测能力进行深度测评。测评结果…

2026主管药师考试备考资料推荐:3大数据维度测评+全阶段资料对比排行

一、2026主管药师考试基础筑牢阶段(考前3-6个月):搭建知识框架,扫清考点盲区 (一)2026考试优选备考资料:《阿虎铂金手册》+《阿虎拿分考典》 1.专业保障理由:阿虎医考教研团队拥有丰富的医考教辅研发经验,自2…