Change Streams 与校验与 WiredTiger 与压缩

共 19 题
📑 题目列表 19 题
#
★★★

1. WiredTiger 存储引擎的特性,MVCC、压缩、文档级锁?

请介绍 WiredTiger 存储引擎的特性,包括 MVCC、压缩与文档级锁?

  • WiredTiger 是 MongoDB 3.2+ 默认引擎
  • MVCC 快照隔离与并发控制
  • 文档级/集合级锁,压缩算法

WiredTiger 是 MongoDB 3.2 起的默认存储引擎,核心特性包括:MVCC(多版本并发控制)——通过快照隔离实现高并发读,读写互不阻塞,写操作通过版本链维护;压缩——支持 snappy、zlib、zstd 等块压缩算法,以及索引前缀压缩,显著减少磁盘占用;锁粒度——采用文档级锁(doc-level locking)与集合级锁,相比 MMAPv1 的全局数据库锁大幅提升并发;此外还支持检查点(checkpoint)、崩溃恢复(journal)、缓存管理(cache eviction)等。WiredTiger 的 MVCC 让读操作不阻塞写操作,写操作之间通过文档级锁减少冲突,是高性能并发的基石。

WiredTiger 的三大特性是 MVCC、压缩、文档级锁。MVCC 提供快照隔离与高并发,压缩降低存储,文档级锁提升写并发。理解这三个特性,能解释 MongoDB 为何比 MMAPv1 并发更高、存储更省。文档级锁是相对 MMAPv1 全局锁的重大进步。

#
★★★

2. Change Streams 与 Kafka 的协同(Debezium MongoDB Connector)?

请说明 Change Streams 与 Kafka 的协同,特别是 Debezium MongoDB Connector 的应用?

  • Change Streams 捕获数据库变更,作为 CDC 数据源
  • Debezium 把 Change Streams 的事件发布到 Kafka
  • 实现实时数据同步与下游消费

Change Streams 是 MongoDB 的变更数据捕获(CDC)机制,能实时捕获集合的插入、更新、删除等变更。与 Kafka 协同的典型场景是:用 Debezium MongoDB Connector(或其同类工具)订阅 MongoDB 的 Change Streams,把变更事件序列化为 Kafka 消息,发布到 Kafka topic,供下游系统(数据仓库、分析、缓存、事件驱动架构)消费。Debezium 支持游标续传(用 resume token 断点续传),保证变更事件不丢失、可回放。这样 MongoDB 的变更即可流式进入 Kafka,实现数据库与业务系统的解耦、实时同步与事件驱动。协同要点是 Change Streams 提供可靠的事件源,Kafka 提供分布式缓冲与多消费者。

Change Streams 与 Kafka 的协同是"CDC + 消息队列"的经典组合。Change Streams 提供数据库变更事件,Debezium 把事件桥接到 Kafka,实现实时数据管道。理解 resume token 的断点续传与 Kafka 的可靠传播,是理解该类协同的关键。这是现代实时数据架构的常用模式。

#
★★★

3. Change Streams 的 resume token、断点续传?

请解释 Change Streams 的 resume token 与断点续传机制?

  • resume token 标识变更流的读取位置
  • 断点续传:从 token 位置继续读取
  • token 对应 oplog 位置,需 oplog 未被覆盖

Change Streams 的 resume token 是标识变更流读取位置的令牌,每个变更事件都携带一个 resume token(可通过 _id 字段或 getResumeToken 获取)。断点续传指:当应用中断或重新启动后,可用之前保存的 resume token 重新打开变更流,从上次位置继续读取,避免重复或丢失事件。resume token 对应 oplog 中的位置(时间戳 + 操作),因此续传要求该 token 对应的 oplog 记录仍然存在(未被覆盖);若 oplog 被覆盖,token 失效,续传失败。应用需持久化 resume token,并在重启时用 resumeAfter/startAfter 恢复变更流。

resume token 是 Change Streams 断点续传的"书签"。理解"token 对应 oplog 位置"与"续传依赖 oplog 未被覆盖"两点,是理解续传机制的关键。应用需保存 token 并定期重连,同时规划 oplog 大小以保证回溯窗口。这是实现可靠变更消费的关键。

#
★★★

4. Change Streams 的概念与应用,实时捕获集合变更?

请解释 Change Streams 的概念及其在实时捕获集合变更中的应用?

  • Change Streams 实时捕获集合级变更操作
  • 支持 insert/update/delete/replace 等事件
  • 应用:实时同步、触发事件、审计、实时分析

Change Streams 是 MongoDB 提供的实时变更捕获机制,允许应用订阅一个或多个集合的变更,实时接收 insert、update、delete、replace 等变更事件。它基于 oplog 实现,变更事件包含操作类型、变更的文档、时间戳等。应用场景广泛:实时数据同步(把变更同步到缓存或搜索引擎)、事件驱动架构(触发下游业务)、审计日志(记录所有变更)、实时分析(实时聚合变更)。Change Streams 与使用事务结合时,事务内变更可在提交后对外可见。它是 MongoDB 实现实时数据处理与 CDC 的核心能力。

Change Streams 的价值是"实时 + 增量"捕获变更,避免轮询。理解它基于 oplog、支持各类变更事件、可配合事务与 resume token,是应用的核心。它让 MongoDB 能作为实时数据源驱动下游系统,是事件驱动与实时数据架构的关键组件。

#
★★★

5. Change Streams 的可用性与限制(open 变更流、事务中的变更、TTL 删除是否产生事件)

请说明 Change Streams 的可用性与限制,包括 open 变更流、事务中的变更、TTL 删除是否产生事件?

  • 变更流需保持 open 状态才能持续接收
  • 事务内变更在提交后对外可见
  • TTL 删除属于 delete 操作,会产生事件

Change Streams 的可用性依赖变更流保持 open(持续打开)状态,应用需长期维持游标并处理断线重连。限制与语义包括:事务中的变更——事务内写入的变更事件在事务提交后才对外可见,未提交事务的变更不会提前暴露,避免读到未提交数据;TTL 删除——TTL 索引的过期删除是 delete 操作,会像普通删除一样产生 delete 变更事件,应用可感知;此外,drop/dropDatabase 等 DDL 会触发 invalidate 事件并终止变更流。变更流还有完整性与顺序保证(分片集群内按分片有序)。理解这些语义,才能正确消费变更而不漏报或误报。

Change Streams 的限制集中在"可见性时机"与"DDL 影响"。事务内变更提交后可见,TTL 删除产生事件,DDL 触发 invalidate。理解这些边界,是正确设计变更消费的关键。尤其 invalidate 会终止游标,应用需感知并重建。

#
★★★

6. drop、dropDatabase、rename 集合为何会触发 Change Streams 的 invalidate 事件并终止游标?应用应如何感知并重建变更流?

请解释为什么 drop、dropDatabase、rename 集合会触发 Change Streams 的 invalidate 事件并终止游标,以及应用应如何感知并重建变更流?

  • invalidate 事件由 DDL 操作(drop/rename 等)触发
  • invalidate 后变更流游标终止,后续事件无法接收
  • 应用需捕获 invalidate 并重建变更流

Change Streams 监听集合的变更,当集合被 drop、数据库被 drop、或集合被 rename 时,集合结构被破坏,oplog 中后续该集合的变更无法继续按原流推送给应用,因此 Change Streams 会触发 invalidate 事件并终止游标。invalidate 是"变更流终止"的哨兵事件,收到后应用无法再用原游标接收事件。应用应监控 invalidate 事件:捕获后关闭旧游标,根据需要重新建立变更流(若集合被重建,则重新打开并可从新位置监听;若需保留历史可用 resume token 但集合已不存在则无法续传)。应用需在代码中处理 invalidate 回调,实现变更流的自动重建与容错。

invalidate 事件是 Change Streams 对"集合结构毁灭"的响应。理解"DDL 破坏流连续性 → 触发 invalidate → 游标终止"的逻辑,是回答的关键。应用必须处理 invalidate 以重建变更流,否则会静默丢失后续事件。这是运维高可用变更消费的核心。

#
★★★

7. Change Streams 依赖 oplog 的时间窗口,resume token 对应的 oplog 被覆盖后为何无法续传?如何规划 oplog 大小?

请解释 Change Streams 依赖 oplog 的时间窗口,resume token 对应的 oplog 被覆盖后为何无法续传,以及如何规划 oplog 大小?

  • Change Streams 基于 oplog,resume token 对应 oplog 位置
  • oplog 是环形缓冲,被覆盖后 token 失效无法续传
  • 通过 oplog 大小规划回溯窗口

Change Streams 基于 oplog 实现,resume token 对应 oplog 中的具体位置(时间戳 + 操作)。oplog 是环形缓冲(capped collection),当写入量超过 oplog 容量时,最早的 oplog 记录会被覆盖。若 resume token 对应的 oplog 记录已被覆盖,Change Streams 无法从该位置继续读取,续传失败(报错 StartupError/处理失败)。因此,要保证长时间断点续传,必须规划足够大的 oplog 大小,使 oplog 覆盖的业务回溯窗口(如 24 小时)大于应用可能中断的时长。规划时需评估集群写入速率与可用磁盘,设置 oplog 大小(--oplogSize 或 rs.resizeOplog)以匹配所需回溯窗口,并监控 oplog 覆盖速率。

Change Streams 与 oplog 的绑定是理解续传的限制所在。oplog 环形覆盖是续传失败的根本原因。规划 oplog 大小要匹配"中断回溯窗口 > 应用的断线时长"。理解"oplog 覆盖 → token 失效"与"oplog 大小决定回溯窗口",是设计可靠变更消费的关键。

#
★★

8. WiredTiger 的压缩算法,snappy、zlib、zstd?

请介绍 WiredTiger 的压缩算法 snappy、zlib、zstd 各自的特点?

  • snappy:速度快、压缩率低
  • zlib:压缩率较高、速度慢
  • zstd:压缩率与速度平衡、现代推荐

WiredTiger 支持多种块压缩算法,通过 block_compressor 配置。snappy 以速度著称,压缩解压极快,但压缩率较低(降低磁盘空间有限);zlib 压缩率较高,能显著减少磁盘占用,但 CPU 开销大、速度慢;zstd 提供平衡的压缩率与速度,压缩率接近 zlib 且速度更快,是性能和空间权衡的现代推荐选择。默认引擎通常用 snappy(版本差异),但追求空间可用 zstd 或 zlib。压缩率越高,磁盘占用越小,但 CPU 与写入延迟越高。选型需在存储空间与 CPU 开销之间权衡:IO 密集、空间敏感选高压缩率(zstd/zlib),CPU 敏感选 snappy。

三种压缩算法的核心权衡是"压缩率 vs 速度"。snappy 快而省 CPU、压缩率低;zlib 压缩率高而慢;zstd 兼顾两者。选型取决于磁盘空间与 CPU 的代价。理解这个权衡,是配置 WiredTiger 压缩的关键。块压缩与索引前缀压缩都影响存储与写放大。

#
★★

9. WiredTiger 的检查点(Checkpoint)机制?

请解释 WiredTiger 的检查点(Checkpoint)机制?

  • 检查点把内存中已提交数据持久化到磁盘
  • 默认每 60 秒或一定日志量生成一次
  • 崩溃恢复以检查点为基础,配合 journal

WiredTiger 的检查点(checkpoint)机制是把内存中已提交的数据持久化到磁盘数据文件的过程。默认情况下,WiredTiger 每 60 秒(或 journal 达到一定大小)生成一个检查点,把缓存中已提交的修改写入磁盘数据文件,并更新检查点元数据。检查点是崩溃恢复的基础:崩溃后,MongoDB 从最近一次检查点恢复,再通过 journal 回放检查点之后未持久化的已提交写入,实现数据不丢失。检查点生成是异步的,会短暂占用 IO,但不会阻塞写入。检查点之间未落盘的数据依赖 journal 保证持久性。

检查点是"数据持久化的锚点"。理解"检查点固化已提交数据 + journal 回放检查点之后的写入"的配合,是理解崩溃恢复的关键。检查点频率决定恢复时回放 journal 的量,默认 60 秒。检查点与 journal 共同保证 WiredTiger 的数据持久性。

#
★★

10. WiredTiger 与原 MMAPv1 引擎的对比?

请对比 WiredTiger 与旧版 MMAPv1 存储引擎?

  • 锁粒度:WiredTiger 文档级锁 vs MMAPv1 全局锁
  • 数据压缩:WiredTiger 支持压缩 vs MMAPv1 无
  • 崩溃恢复与并发能力

WiredTiger 是 MongoDB 3.2+ 默认引擎,MMAPv1 是旧版引擎(已废弃)。主要差异:锁粒度——MMAPv1 使用全局数据库锁,写操作之间基本串行,并发低;WiredTiger 采用文档级锁,写并发大幅提升。压缩——MMAPv1 无压缩,磁盘占用大;WiredTiger 支持 snappy/zlib/zstd 压缩,显著省存储。崩溃恢复——MMAPv1 依赖应用层 journal 恢复,可靠性差;WiredTiger 自带检查点与 journal,崩溃恢复更可靠。此外 WiredTiger 支持 MVCC 快照、缓存驱逐等,性能与功能全面优于 MMAPv1。因此 MMAPv1 已被移除,WiredTiger 成为唯一选择。

WiredTiger vs MMAPv1 的核心差异是"并发、压缩、恢复"。文档级锁解决写并发,压缩解决存储,检查点+journal 解决可靠性。这三方面 WiredTiger 全面胜出,故 MMAPv1 被淘汰。理解这些差异,能解释 MongoDB 引擎演进的原因。

#
★★

11. Change Streams 的事件语义,insert/update/replace/delete 与事务事件?

请解释 Change Streams 的事件语义:insert/update/replace/delete 与事务事件?

  • 各事件类型(insert/update/replace/delete)的触发条件
  • 事务内变更以事务提交后可见
  • 事件字段(operationType、documentKey 等)

Change Streams 的事件按操作类型区分。insert:新文档插入时触发,事件包含 fullDocument;update:文档更新时触发,事件包含 updateDescription(被修改的字段);replace:用新文档整体替换旧文档(replaceOne)时触发;delete:文档删除时触发,事件包含 documentKey(被删文档的 _id)。事务事件:当变更发生在事务内时,事件在事务提交后对外可见,且同一事务的多个变更会一起暴露。事件字段包括 operationType、documentKey、fullDocument、updateDescription、timestamp 等。理解各事件语义,才能准确消费变更做下游处理。

事件语义的核心是"操作类型 → 事件内容"。insert 带全文,update 带变更描述,delete 带键,replace 是整体替换。事务内变更提交后可见。理解这些映射,是正确解析变更事件、实现业务逻辑的关键。尤其 update 与 replace 的区别(字段级 vs 整文档替换)。

#
★★

12. Change Streams 的断点恢复,resume token 的实现与集群切换?

请解释 Change Streams 的断点恢复:resume token 的实现与集群切换时的行为?

  • resume token 基于 oplog 时间戳实现
  • 集群切换(primary 变更)后 resume token 仍可用
  • 分片集群中 token 绑定分片

Change Streams 的断点恢复依赖 resume token。resume token 在实现上基于 oplog 的时间戳(clusterTime)与操作位置,是全局唯一的标识。集群切换(如 primary 故障转移)后,应用持有之前保存的 resume token,仍可重新打开变更流并从原位置继续读取——因为 oplog 在副本集所有节点间同步,token 对应的位置在切换后的新 primary 上仍能找到(只要 oplog 未被覆盖)。在分片集群中,resume token 绑定具体分片,应用需针对每个分片保存 token 以恢复各自的事件流。断点恢复的核心是"token 标识唯一位置 + oplog 保留该位置"。

resume token 的"跨集群切换可用"来自 token 基于 oplog 时间戳、oplog 在副本集同步。理解"token 唯一位置 + oplog 保留"是断点恢复的根基。分片集群中 token 按分片管理。应用需持久化 token 并在重连时使用,实现可靠续传。

#
★★

13. validator 的 validationLevel/validationAction(warn/error)与存量文档的兼容处理

请解释集合校验 validator 的 validationLevel/validationAction(warn/error)以及存量文档的兼容处理?

  • validator 定义文档校验规则
  • validationLevel 决定校验范围(strict/modest/off)
  • validationAction 决定违规处理(error/warn)

MongoDB 集合的 validator 用于定义文档结构校验规则,限制写入文档的字段与类型。validationLevel 决定校验的严格程度:strict 校验所有插入和更新;modest 只校验插入和已有文档的更新,不校验不满足条件的文档;off 关闭校验。validationAction 决定校验失败的处置:error 拒绝写入并报错;warn 记录警告日志但不阻止写入。存量文档兼容:validator 默认只对后续写入生效,不校验存量文档;若需校验存量文档,可用 validationLevel: strict 配合 modest 或手动扫描。设计校验时,用 warn 先观察违规情况,确认无误后再切到 error,避免误伤业务。

validator 的维度是"校验范围"(validationLevel)与"违规处置"(validationAction)。理解 strict/modest、error/warn 的组合,是设计校验策略的关键。上线校验建议先用 warn 观察,再切 error。存量文档需单独处理,validator 默认不校验存量。

#
★★

14. WiredTiger 的缓存管理与驱逐(cache_size、eviction)对读写延迟的影响

请说明 WiredTiger 的缓存管理与驱逐对读写延迟的影响?

  • cache_size 控制缓存大小
  • eviction 在缓存满时驱逐数据到磁盘
  • 缓存不足导致写放大与延迟上升

WiredTiger 使用内存缓存(cache)来缓冲读写,cache_size 参数控制缓存大小(默认约 50% 内存)。当缓存接近满时,WiredTiger 触发驱逐(eviction),把缓存中的脏数据写入磁盘并释放空间。驱逐是异步的,但若写入速率超过驱逐能力,缓存被占满,写操作会阻塞等待驱逐,导致延迟上升;读操作若缓存未命中则需从磁盘读取,延迟升高。缓存大小配置不当(过小)会引起频繁驱逐、写放大与延迟抖动;过大则占用内存影响其他组件。因此需监控缓存命中率与驱逐,合理设置 cache_size,并与 journal、检查点配合,避免缓存成为瓶颈。

缓存与驱逐是 WiredTiger 性能的关键。cache_size 决定缓存容量,驱逐发生在缓存满时。理解"缓存满 → 驱逐阻塞 → 写延迟上升"的连锁,是调优的关键。合理配置缓存并监控驱逐,能避免读写延迟退化。缓存命中率与驱逐速率是重要监控指标。

#
★★

15. WiredTiger 的 journal 与 checkpoint 如何配合崩溃恢复?未 checkpoint 的数据如何通过 journal 回放恢复?

请解释 WiredTiger 的 journal 与 checkpoint 如何配合崩溃恢复,未 checkpoint 的数据如何通过 journal 回放恢复?

  • checkpoint 固化已提交数据到磁盘
  • journal 记录未 checkpoint 的已提交写入
  • 崩溃后从 checkpoint 恢复 + journal 回放

WiredTiger 的崩溃恢复依赖 checkpoint 与 journal 的配合。checkpoint 周期性把已提交数据持久化到磁盘数据文件;journal(日志)记录 checkpoint 之后产生的已提交写入操作。崩溃发生时,内存中可能还有未 checkpoint 的已提交数据。恢复流程:从最近一次 checkpoint 恢复数据文件,然后回放(replay)journal 中 checkpoint 之后记录的写入,把未 checkpoint 的已提交数据重新应用到数据文件,从而不丢失已提交写入。journal 采用追加写,保证已提交写入先落 journal 再落数据文件,因此崩溃时 journal 中的写入可恢复。未 checkpoint 的数据通过 journal 回放恢复,是 WiredTiger 持久性的保证。

checkpoint 与 journal 是"锚点 + 增量"的关系。checkpoint 提供恢复基线,journal 记录基线后的写入供回放。理解"未 checkpoint 数据靠 journal 回放恢复"是回答的核心。journal 的持久性(先写日志)保证已提交写入不丢。这是 WiredTiger 崩溃恢复的完整机制。

#
★★

16. WiredTiger 的 block_compressor 与索引前缀压缩对写放大和查询性能有何影响?压缩率与 CPU 开销如何权衡?

请说明 WiredTiger 的 block_compressor 与索引前缀压缩对写放大和查询性能的影响,以及压缩率与 CPU 开销的权衡?

  • block_compressor 对数据块压缩,减少磁盘占用
  • 索引前缀压缩减少索引存储
  • 压缩率高但 CPU 开销大,影响写放大与查询延迟

WiredTiger 的 block_compressor 配置数据块的压缩算法,对数据文件做块级压缩,减少磁盘占用;索引前缀压缩则对索引键的公共前缀做压缩,减少索引存储。压缩对写放大和查询性能的影响:压缩减少落盘数据量,降低磁盘 IO 与写放大(减少物理写入),但压缩/解压消耗 CPU;压缩率高(如 zstd/zlib)时,压缩慢、CPU 开销大,写延迟上升,查询解压也增加 CPU 与延迟;压缩率低(如 snappy)时 CPU 省、但磁盘占用大。因此权衡在于:压缩率越高,磁盘越省、写放大越低,但 CPU 开销越大、吞吐与延迟受影响;反之亦然。需按存储空间成本与 CPU 预算选择。

压缩的权衡是"磁盘空间 vs CPU 开销"。理解压缩"减少写放大与磁盘 IO,但增加 CPU",是选型的关键。块压缩与索引前缀压缩都体现此权衡。对 IO 敏感选压缩率低(snappy)、对空间敏感选高压缩率(zstd/zlib),并监控 CPU 与延迟。

#

17. Change Streams 与事务,事务内写入的变更事件何时对外可见?

请解释 Change Streams 与事务的关系:事务内写入的变更事件何时对外可见?

  • 事务内变更在事务提交后才对外可见
  • 未提交事务的变更不产生可见事件
  • 事务回滚则不产生事件

Change Streams 与事务结合时,事务内写入的变更事件在事务提交后才对外可见。也就是说,未提交(进行中)事务内的写入不会立即产生可被变更流消费的事件;只有当事务成功提交后,其中的所有变更才一起对外暴露。若事务回滚,则其写入不会产生任何变更事件(因为未提交)。这一语义保证了变更流消费者不会读到未提交的、可能被回滚的数据,符合事务的原子性与一致性。应用消费变更流时,可将事务内变更视为批量提交后在提交点统一可见。

事务内变更"提交后可见"是保证隔离性的关键。理解"提交前不暴露、回滚不暴露、提交后统一暴露",是回答事务与变更流关系的核心。这避免了消费者读到中间态。变更流与事务的配合实现了"提交即可见"的可靠事件语义。

#

18. WiredTiger 的快照隔离与并发控制,MVCC 与锁的配合?

请解释 WiredTiger 的快照隔离与并发控制,以及 MVCC 与锁的配合?

  • 快照隔离:读操作基于一致快照,不阻塞写
  • MVCC 维护版本,写冲突检测
  • 锁用于写写冲突控制

WiredTiger 的快照隔离与并发控制基于 MVCC 与锁的配合。快照隔离:每个读操作基于一个一致快照,读不需等待写,读见到的数据是快照时刻的已提交版本,读写互不阻塞。MVCC:通过维护数据的多个版本(版本链),让不同快照看到不同版本,支持高并发读;写入时若版本冲突,进行冲突检测。锁:WiredTiger 用文档级锁控制写之间对同一文档的冲突,写写冲突时后到者等待或失败。配合方式:读走快照(MVCC 无锁),写走锁(文档级),读写并发、写写串行化。这样在保证隔离的同时最大化并发。

"读走 MVCC 快照、写走文档级锁"是 WiredTiger 并发控制的核心。理解快照隔离让读不阻塞写、锁让写写不冲突,是回答的关键。事务利用快照隔离实现可重复读,锁保证写冲突的正确性。这种配合是实现高并发与一致性的关键。

#

19. Change Streams 在分片集群中的事件顺序保证(全局顺序 vs 分片内顺序)

请说明 Change Streams 在分片集群中的事件顺序保证(全局顺序 vs 分片内顺序)?

  • 分片集群中无法保证全局顺序
  • 同一分片内保证顺序
  • 跨分片事件需按分片消费

在分片集群中,Change Streams 的事件顺序保证是"分片内有序、全局无序"。这是因为分片集群中每个分片持有不同数据,各分片独立产生事件,mongos 综合各分片事件时无法保证跨分片的全局顺序。因此:同一分片内的事件按发生顺序(oplog 顺序)保证;跨分片的事件顺序不保证,可能交错。应用若要获得全局顺序,需按分片消费事件(针对每个分片 open 变更流)并自行合并/排序,或接受分片内顺序。设计消费逻辑时,需意识到全局顺序的限制,避免依赖跨分片事件的相对顺序。

分片集群的顺序保证是"分片内有序、全局无序"。理解这一限制,才能正确设计跨分片事件的消费与合并。需要全局顺序时按分片单独消费并合并。这是分布式事件流的关键约束。