Change Stream 同步
概述
Change Stream 同步基于 MongoDB 原生 Change Stream 机制,把通过过滤的变更事件分发给一个或多个 target。它适合备份库、投影表、缓存失效回调和其他异步 CDC 工作流。
核心特性
- ✅ 异步 CDC:基于 MongoDB Change Stream,延迟取决于 MongoDB、网络与 target 负载
- ✅ 解耦设计:主库写入不会等待 target apply 回调
- ✅ 断点续传:匹配的目标全部同步成功后保存 Resume Token,重启后从最近一次成功持久化的 token 继续
- ✅ 多目标支持:同时同步到多个备份库
- ✅ 数据过滤:自定义过滤逻辑
- ✅ 数据转换:支持脱敏、字段转换
- ✅ 生命周期可观测:同步统计暴露运行状态与错误计数,便于监控和重启
- ✅ 健康检查:为托管 target 配置健康检查
⚠️ 前提条件
必须满足
-
MongoDB Replica Set 🔴
-
MongoDB 版本 >= 4.0 🔴
-
用户权限 🔴
🚀 快速开始
基础配置
📖 配置选项
sync 配置
transform 是 manager 级转换钩子。每个通过过滤的 change event 只会在分发到匹配 targets 前执行一次,因此所有 target 会收到同一个转换后的 document。Delete 事件通常没有 fullDocument;自定义 target 应能处理 document === undefined,并使用 event.documentKey 完成删除处理。
targets[].配置
resumeToken 配置
Resume Token 持久化默认是 strict。文件模式会先写入同目录临时文件、fsync、把上一份 token 备份为 <path>.bak,再通过原子 rename 替换正式文件。启动时也会校验已保存 token:strictLoad 为 true 时,损坏 token 会快速失败,而不是静默按无 resume token 启动。匹配的 target 全部成功应用事件后,monSQLize 会先保存该事件的 resume token;只有保存成功后才推进 syncedCount。如果 token 保存在配置的重试后仍失败,或任一匹配 target 应用事件失败,manager 会记录错误、关闭当前 change stream、将 isRunning 标记为 false,并停止处理后续排队事件。这是 at-least-once 契约,不是 exactly-once:target apply 成功但 token 保存前崩溃时,同一事件可能重放。只有兼容旧 best-effort token 存储行为时才设置 strictSave: false 与 strictLoad: false;此时进程重启后可能重放已应用事件,或在旧 token 损坏时按无 token 启动。内置 MongoDB target 是幂等的(replaceOne(..., { upsert: true }) / deleteOne());自定义 apply target 仍建议按 change event _id 做幂等或去重。
idempotency 配置
sync.idempotency 是可选能力,默认关闭。启用后,manager 默认根据 change event _id 为每个 target 生成幂等 key;也可以通过 keyBuilder 自定义。key 已存在时,该 target 会被跳过,并在所有 eligible targets 都被处理后继续保存 resume token。跨进程重启保护需要传入 durable store;未传 store 时的内存 fallback 只能保护同进程内重复投递。markMode: 'success' 在 apply 成功后记录;markMode: 'start' 会在 apply 前记录,它能降低 unknown-success 重复写风险,但 marker 写入后若 apply 失败,runtime replay 可能会跳过该 target,因此只适用于 target 自身有 durable 幂等与恢复路径的场景。
💡 使用示例
示例1:多备份目标
示例2:数据过滤
示例3:数据脱敏
示例4:Redis Resume Token
📊 性能影响
🔧 API
获取统计信息
手动停止同步
手动启动同步
❓ 常见问题
Q1: 提示 "Change Stream 不可用"
原因: MongoDB 不是 Replica Set
解决:
Q2: 同步有延迟?
原因: 网络延迟、备份库性能
解决:
- 检查网络延迟:
ping backup-host - 检查备份库性能:
db.serverStatus() - 减少同步的集合数量
Q3: Resume Token 丢失怎么办?
影响: 重启后从当前时间开始同步,丢失中间数据
解决:
- 使用 Redis 存储 Resume Token
- 定期备份 Resume Token 文件
- 手动全量同步一次
Q4: 如何处理同步失败?
自动处理:
- 已经成功应用该事件的 target 不会回滚,但任一 target 失败都会在 resume token 推进前停止 manager
- Resume Token 保存失败会在推进 token 前停止 sync manager
- Change Stream driver 错误与意外 stream close 会记录日志并体现在 stats 中;生产应监控
isRunning、errorCount与lastError,必要时由进程管理器或应用重启 manager/runtime
手动处理: