图解 MongoDB 01|为什么是文档数据库:driver、mongod 和 WiredTiger 三段路
MongoDB 被讲成「一个存 JSON 的数据库」,但它其实是 driver、mongod、WiredTiger 三段路拼出来的。本文聊聊这条缝在哪里、为什么这么设计,以及看懂它能解决什么问题。
从文档模型与 BSON 开始,拆到索引优化、WiredTiger 存储引擎、复制集、分片集群和架构选型。
适合想从命令手册深入到存储引擎、高可用拓扑和选型判断的后端工程师。
文档数据库定位、BSON、CRUD 链路、模型设计、模式演进与事务。
索引结构、类型、ESR、explain、覆盖查询与慢查询排查。
WiredTiger、Cache、journal、压缩与大集合工作集。
复制集、oplog、延迟、选举、读写关注与两地三中心。
分片架构、片键、均衡器、陷阱与查询路由。
备份恢复、Change Stream、监控、安全、数据中台与选型。
MongoDB 被讲成「一个存 JSON 的数据库」,但它其实是 driver、mongod、WiredTiger 三段路拼出来的。本文聊聊这条缝在哪里、为什么这么设计,以及看懂它能解决什么问题。
MongoDB 的文档被讲成「JSON 对象」,但底层流动的是 BSON——一种带类型标记和长度前缀的二进制格式。本文讲清楚 BSON 长什么样、为什么它比 JSON 更快但可能更大,以及它怎么影响你选字段类型。
find 被讲成「查文档」,但一条查询要从 driver 穿过网络层、解析、优化器、执行计划,再落到 WiredTiger 的 B-tree。本文讲清楚这条链路每一段在做什么,以及慢查询最可能卡在哪。
MongoDB 的索引被讲成「给字段建个索引就快了」,但底层它是 WiredTiger 里独立的一棵 B-tree。本文讲清楚索引条目长什么样、为什么查得快写得慢,以及索引数量怎么放大写入成本。
MongoDB 建模被讲成「想怎么存就怎么存」,但内嵌和引用是两种访问局部性截然不同的取舍。本文讲清楚什么时候该内嵌、什么时候该引用,以及为什么无限增长的数组是文档模型的头号反模式。
MongoDB 的「无 schema」被讲成「随便加字段」,但放任演进会让一个集合里同时存在三代结构。本文讲清楚 schemaless 的真实代价,以及用 $jsonSchema 校验和惰性迁移把灵活收敛成可控的方法。
MongoDB 的索引被笼统讲成「加索引就快」,但单键、复合、多键、地理、全文、TTL、哈希是七种完全不同的访问形状。本文讲清楚每种索引服务什么查询,以及建错类型等于白建。
复合索引被讲成「把查询字段都放进去」,但字段顺序决定索引能用多少。本文讲清楚 ESR 原则——等值在前、排序居中、范围在尾,顺序错了索引只能用一半。
explain 被当成「看一眼有没有走索引」,但它分 queryPlanner、executionStats、allPlansExecution 三层。本文讲清楚每层看什么,以及 totalKeysExamined 和 totalDocsExamined 这对指标怎么判断查询健康。
覆盖查询被当成「高级技巧」,但它的本质是让索引里就有全部需要的字段,连回表都省了。本文讲清楚 totalDocsExamined=0 怎么达成,以及它和查询路由的关系。
慢查询排查最怕一上来就加索引。本文把发现、定位、修复、验证串成一套闭环,讲清楚怎么用 Profile 找慢查询、用 explain 分层判断,再按五条分支收敛到具体动作。
把索引模型、类型、ESR、explain、覆盖查询、慢查询排查串成一张地图。本文是索引与查询优化阶段的收束,收成代价观、设计观、验证观三条主线。
WiredTiger 被当成「MongoDB 默认引擎」一笔带过,但它是性能抖动的真正源头。本文讲清楚数据在 B-tree 页里怎么存、Cache 怎么缓存热页、checkpoint 怎么把脏页刷盘,以及为什么写入会周期性抖动。
Cache 被当成「一块内存」,但它的淘汰机制是 MongoDB 性能抖动的直接来源。本文讲清楚 Cache 什么时候开始淘汰、脏页怎么刷盘,以及为什么应用线程被拉来淘汰会让查询突然变慢。
journal 被当成「一个日志文件」,但它是写入不丢的真正保证。本文讲清楚一次写入怎么先记 journal 再改 Cache,checkpoint 怎么刷盘,崩溃后怎么从 checkpoint 回放 journal 恢复,以及 writeConcern 怎么调持久性档位。
压缩被当成「省磁盘的功能」,但它同时影响 Cache 命中率和 CPU 开销。本文讲清楚 snappy、zstd、column compression 三种方式的取舍,以及为什么压缩率不是越高越好。
数据超过内存是 MongoDB 最常见的容量拐点。本文讲清楚工作集是什么、它和 Cache 的关系,以及工作集超载时的四种应对:加内存、分片、冷热分离、优化访问。
复制集被讲成「主从复制」,但它是带自动 failover 的高可用集群。本文讲清楚 Primary、Secondary、Arbiter 各自的职责、为什么必须是奇数节点,以及复制集怎么实现高可用。
复制被讲成「Primary 的数据同步到 Secondary」,但底层流动的是 oplog——记录操作而非文档。本文讲清楚 oplog 是什么、为什么必须幂等、它是固定大小的环形缓冲会带来什么问题。
复制延迟被当成「正常现象」,但持续延迟会让 Secondary 读到旧数据、failover 丢数据。本文讲清楚延迟的根因——产生速度 vs 重放速度,以及怎么监控和应对。
failover 被当成「自动切换」,但它背后是心跳检测和多数派投票的选举协议。本文讲清楚 Primary 宕机后新 Primary 怎么选出来、选举期间为什么写不可用、以及脑裂怎么防。
读写关注被当成「几个配置项」,但它们是持久性和一致性的核心旋钮。本文讲清楚 writeConcern 怎么控制写到几个节点算成功、readPreference 怎么选读哪个节点,以及怎么组合出从最快到最稳的完整光谱。
三节点复制集能扛单机故障,但扛不住机房故障。本文讲清楚两地三中心的 5 节点拓扑怎么通过多数派和优先级,保证任一机房挂了集群仍能存活和快速切换。
分片被当成「让 MongoDB 更强」的功能,但它本质是单机到顶后的无奈之选。本文讲清楚垂直扩容的天花板在哪、分片怎么把数据和工作集分散,以及什么时候真的该上分片。
分片集群被讲成「多台机器存数据」,但它有三层架构。本文讲清楚 mongos 怎么路由、config server 存什么元数据、shard 为什么本身是复制集,以及应用为什么对分片无感知。
片键被当成「随便选个字段」,但它是分片集群几乎改不了的决定。本文讲清楚片键要同时满足基数高、写分散、查询定向三个目标,以及常见片键的取舍。
范围分片和哈希分片被笼统讲成「两种分片」,但它们决定了查询能否定向、写入会不会热点。本文讲清楚两者的机制和取舍,以及怎么在范围查询和写均匀之间兼得。
chunk 被当成「分片的最小单位」,但它的分裂、迁移和 jumbo 问题是分片运维的核心。本文讲清楚 chunk 怎么划分、balancer 怎么均衡、为什么会出现无法迁移的 jumbo chunk。
分片上线后最常踩的三个坑:无法迁移的 jumbo chunk、残留的孤儿文档、单 shard 写入热点。本文讲清楚每个陷阱的成因、现象和解法,根源都指向片键设计。
分片集群的查询被笼统讲成「查数据」,但带片键的查询定向到单 shard,不带片键的查询广播到所有 shard。本文讲清楚两者的代价差别,以及怎么让查询尽量走定向。
备份被当成「会 mongodump 就行」,但生产备份要考虑全量快照、时间点恢复和恢复演练。本文讲清楚三种备份方式的适用场景,以及为什么没演练过的备份等于没备份。
Change Stream 被当成「监听数据变更的 API」,但底层是 oplog 的事件化封装。本文讲清楚它怎么把数据变更变成可订阅、可断点续传的事件流,以及它的至少一次语义和适用场景。
监控被当成「看几个指标」,但 MongoDB 性能问题分散在负载、连接、内存、复制四个维度。本文讲清楚怎么分类看指标,以及调优从低成本到高成本的正确优先级。
安全被当成「开个鉴权就行」,但生产 MongoDB 要从认证、授权、传输加密到字段级加密建四道防线。本文讲清楚每道防线的作用,以及敏感数据怎么做到库泄漏也是密文。
MongoDB 被当成「万能数据库」,但它有自己的擅长和不擅长。本文讲清楚 MongoDB 在典型数据架构里常做业务主库,配合 Redis、ES、数仓、消息队列各司其职,以及它不适合做什么。
图解 MongoDB 系列的收束篇。把 36 讲六个阶段串成一张地图,收成「该不该选 MongoDB」的判断——它是灵活的业务主库,不是万能库,用对场景才强大。