很多业务需要「数据一变就触发动作」:订单状态变了就推消息、用户资料改了就同步到搜索引擎、库存变了就刷新缓存。传统做法是应用在写入后手动触发,但这样耦合重、容易漏。MongoDB 的 Change Stream 提供了更优雅的方案——把数据变更变成应用可订阅的事件流。

这一篇讲清楚 Change Stream 的底层机制、关键特性和适用场景。

先把机制边界说清楚

Change Stream 是 MongoDB 3.6 引入的能力,它把 oplog(复制日志)的变更,包装成应用可订阅的、结构化的事件流。应用开启一个 Change Stream,就能实时收到集合上的 insert/update/delete 事件。

关键认知:Change Stream 的底层就是 oplog。前面讲过,oplog 记录了 Primary 的每个写操作。Change Stream 本质上是应用「订阅」oplog 的变更,MongoDB 把原始的 oplog 操作转换成更友好的变更事件(包含完整文档、操作类型、时间戳等)。

因为依赖 oplog,Change Stream 有几个前提:必须连复制集或分片集群(单机没有 oplog);事件的保留受 oplog 窗口限制(oplog 覆盖外的旧事件拿不到)。

Change Stream 的工作方式

Change Stream:从 oplog 到事件驱动

数据流:MongoDB 写入 → 记 oplog → Change Stream 订阅 oplog → 转成变更事件 → 下游应用消费。下游应用可以是同步到 Elasticsearch、刷新缓存、触发业务逻辑、发通知等。

关键特性

resumeToken(断点续传)。Change Stream 的核心价值之一。每个变更事件带一个 resumeToken,应用把它持久化下来。如果应用重启,可以用 resumeToken 从断点继续消费,不丢事件、不重复处理已完成的。这让 Change Stream 适合长时间运行的事件消费。

过滤。Change Stream 支持按集合、操作类型、文档内容过滤。比如只订阅 orders 集合的 update 事件,或只订阅 status 变为 paid 的文档。过滤在服务端做,减少传给应用的事件量。

至少一次语义(at-least-once)。Change Stream 保证事件不丢,但可能重复——网络抖动或应用重启时,某些事件可能被重新投递。所以下游消费必须幂等:重复处理同一个事件不能产生副作用。这和所有基于日志的 CDC(变更数据捕获)系统一样。

依赖 oplog 窗口。Change Stream 能回溯的事件,受 oplog 保留窗口限制。如果一个应用离线太久,超过了 oplog 窗口,它 resume 时会失败(要找的事件已被覆盖)。所以 oplog 要足够大,覆盖应用最长的离线时间。

适用场景

Change Stream 特别适合这几类「数据变更触发」的场景:

数据同步(CDC)。把 MongoDB 的变更实时同步到 Elasticsearch、Redis、数据仓库。比起应用双写(写 MongoDB 同时写 ES),Change Stream 解耦了主流程,主写入不用管下游,且天然保证顺序。

缓存刷新。数据变更时自动失效或更新缓存,避免缓存和数据库不一致。比定时刷新缓存更及时、更省资源。

业务事件触发。订单状态变更触发通知、库存变化触发补货、用户行为触发风控。把「数据变更」作为事件源,驱动后续业务。

审计与日志。记录关键集合的所有变更,用于审计、合规、数据回溯。

Change Stream vs 双写 vs 定时轮询

对比几种「数据变更感知」方案:

  • 应用双写:写 DB 时同时写下游。耦合重,主流程要管下游,且不能保证一致性(一边成功一边失败)。
  • 定时轮询:定期查 DB 找变更。延迟高、浪费资源(大部分轮询没有变更)。
  • Change Stream:事件驱动,实时、解耦、有序。代价是依赖 oplog、下游要幂等。

Change Stream 在实时性、解耦性上明显优于前两者,是 MongoDB 场景下做 CDC 的首选。

注意事项

下游必须幂等。至少一次语义意味着可能重复,下游消费要做去重或幂等处理。

oplog 要够大。覆盖消费方最长的离线时间,否则 resume 失败。

性能影响。Change Stream 本身读 oplog,对 Primary 性能影响小,但大量消费方订阅会增加 oplog 读取压力。

分片集群。分片集群的 Change Stream 要聚合所有 shard 的变更,mongos 协调,有额外开销,但用法和复制集一致。

判断框架

  • Change Stream 底层是 oplog,把变更包装成事件流。
  • resumeToken 支持断点续传,适合长期消费。
  • 至少一次语义:不丢但可能重复,下游必须幂等。
  • 适合 CDC、缓存刷新、业务触发、审计。
  • 优于双写(解耦)和轮询(实时)。
  • oplog 要覆盖消费方最长离线时间。

下一篇讲监控与性能调优。


关于十三Tech

我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。

我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。

如果你想继续跟完这套「图解 MongoDB」,欢迎关注公众号 「十三Tech」。后续会按运维和架构选型这条线更新。

十三Tech公众号二维码