1.2 MongoDB架构与版本兼容事故


1.2 MongoDB 架构与版本兼容事故

本节摘要:MongoDB 的核心进程是 mongod,配合 mongo/mongosh 客户端与 WiredTiger 存储引擎工作。本节从一次"升级服务器没升级驱动"的上线事故讲架构组件与版本兼容规则,并给出读日志的入口。

事故档案 02:升级当晚的连环报错

某团队把服务器从 4.0 升到 6.0,应用侧的旧驱动没动。上线当晚,日志里刷出大量 Unsupported OP_QUERY 与命令不识别错误,写入全部失败。根因:MongoDB 5.1 起移除了旧版 OP_QUERY 协议,老驱动只会说"旧方言"。

这条事故引出的架构图景:

单机架构三件套

  • mongod:数据服务进程,一切的主人。默认端口 27017。
  • 存储引擎 WiredTiger:负责并发控制(文档级锁)、压缩、检查点。缓存默认取 (RAM - 1GB) 的一半,这个数字在第 10 章的缓存驱逐事故里会再次出现。
  • 客户端:交互式 shell(mongosh)与应用驱动(Node.js、Java、Python 等),协议兼容性由驱动版本决定。

版本兼容对照(节选)

服务器版本 最低驱动要求 备注
4.4 各语言驱动需升到当年版本 移除旧扫描方式
5.1+ 需支持 OP_MSG 协议 OP_QUERY 下线
6.0/7.0 官方推荐最新驱动 mongosh 全面取代 mongo

💡 版本升级检查清单里,"应用驱动版本"要和"服务器版本"放在同一行。只升一头的升级等于没升。

第一次连接与日志入口

// mongosh 连接后先看身份 db.version(); db.getServerStorageEngine(); // 确认 wiredTiger db.hello(); // 查看实例角色,复制集时代更常用

排障时先看 mongod 日志(配置项 systemLog),启动失败、慢操作、选举事件全在里面。日志是 JSON 行格式,字段 s 表示严重级别,c 表示组件,按这两个字段过滤效率最高。

事故复盘:一次本可避免的连环失败

这次事故的定位过程值得完整走一遍。晚上十点切换流量,两分钟后应用日志开始刷异常,错误信息有两类:一类是连接直接被断开,一类是发送命令后收到 Unknown command。运维同学先怀疑网络,抓包看连接建立正常,TCP 层没问题;再看 mongod 日志,发现服务器端记录的是协议层面的拒绝。到这一步方向才转对:客户端发出的请求使用旧版 OP_QUERY 操作码,服务器在 5.1 之后只接受 OP_MSG。

为什么测试环境没拦住?测试环境的应用连接的是另一个还没升级的 4.0 实例,等于升级后的服务器从头到尾没被真实流量打过。这是兼容性事故的典型模式:环境不一致掩盖了协议断层。

修复动作很快:把 Node.js 驱动从 2.x 升到 5.x,Java 驱动同步升级,重发后错误消失。但复盘时算了一笔账——如果升级顺序倒过来,先升驱动再升服务器,旧驱动同样会有兼容窗口。正确做法是查驱动发布说明里的兼容矩阵,选一个双向兼容的版本做中转,先升驱动、观察、再升服务器。

# 升级前先做协议与能力核对 mongosh --quiet --eval 'db.version()' # 6.0.12 mongosh --quiet --eval 'db.hello().maxWireVersion' # 21 ← 驱动支持的 wireVersion 必须不高于此值 node -e 'const d=require("mongodb"); console.log(d.WireDescription?.maxWireVersion ?? "查驱动文档")'

maxWireVersion 是驱动与服务器协商协议版本的机制:驱动报自己支持的版本,服务器取交集。两边差一个大版本通常还能通信,差两个大版本就开始出现"命令不识别"这类模糊报错,这也是为什么升级跨度不要超过一个大版本,4.0 直升 6.0 本身就踩了红线——官方升级路径是 4.0 → 4.2 → 4.4 → 5.0 → 6.0,逐版本升并设置 clusterCompatibilility 观察一个周期。

存储引擎为什么重要

把 WiredTiger 单独拿出来讲,因为它决定了三个日常能感知的现象。第一是并发控制:文档级并发意味着两个写操作只要不碰同一个文档就互不阻塞,这在关系库行锁直觉之外还多了一层"集合内高并发写入不排队"的体验。第二是压缩:默认 snappy 压缩,磁盘占用通常是内存数据体积的一半以下,对日志类集合换成 zstd 能再省三成,代价是 CPU 略升。第三是检查点机制:引擎每分钟或 journal 满 2GB 做一次检查点,把脏页刷盘,检查点之间的崩溃恢复靠 journal 重放——所以 journal 所在磁盘的写入延迟直接决定写吞吐上限。

// 观察存储引擎行为的三条常用命令 db.serverStatus().wiredTiger.cache; // 关注 "bytes currently in the cache" 与 "tracked dirty bytes" // 缓存占用接近 max 与 eviction 频率飙升,就是第 10 章缓存驱逐事故的前兆 db.serverStatus().wiredTiger.concurrentTransactions; // read/write available tickets,归零说明并发槽耗尽 db.stats().storageEngine; // { name: "wiredTiger" }

本节要点回顾

  • 架构三件套:mongod 进程、WiredTiger 引擎、客户端协议;
  • 兼容规则:驱动与服务器必须同批升级,旧协议已被移除;
  • 缓存默认值:约 (RAM - 1GB) 的一半,调优时绕不开;
  • 日志入口:systemLog 输出的 JSON 行,按 sc 字段过滤。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U