bigywater.tech
MongoDB · 54

写关注 w:1、majority、j:true 的耗时对比

w:1、w:majority、j:true 的延迟差多少?副本不够时 w:majority 会怎样?wtimeout 的错误意味着写入失败了吗?这篇在真实的 3 节点副本集上逐个验证。

0.2 对 4.0 ms
w:1 与 w:majority 的单条 insert 中位延迟
code 64
w:3 在只剩 2 个节点时的 wtimeout 错误,但文档已经写进了 primary
w: majority
3 节点副本集上没有显式设置时的默认写关注

副本集

实测 · 本机执行输出
  成员状态:9901=PRIMARY, 9902=SECONDARY, 9903=SECONDARY
  # 集群的默认写关注(没有显式设置时)
  test> db.adminCommand({getDefaultRWConcern: 1}).defaultWriteConcern
  { w: 'majority', wtimeout: 0 }
  test> var h = db.hello(); ({setName: h.setName, isWritablePrimary: h.isWritablePrimary, members: h.hosts.length, majority: Math.floor(h.hosts.length / 2) + 1})
  { setName: 'rsm46', isWritablePrimary: true, members: 3, majority: 2 }

一个 primary、两个 secondary,默认写关注是 w: majority。

延迟

实测 · 本机执行输出
  写关注                              中位数       p99
  w:0                           0.0 ms    0.2 ms
  w:1                           0.2 ms    0.7 ms
  w:1, j:true                   4.0 ms    9.0 ms
  w:2                           0.6 ms    1.5 ms
  w:majority                    4.0 ms    8.1 ms
  w:3                           0.6 ms    1.3 ms
  w:majority, j:true            4.0 ms    8.4 ms

单条 insert:w:1 0.2 ms;w:2 / w:3 0.6 ms;j:true 与 w:majority 约 4 ms,因为要等 journal 落盘。

secondary 挂掉

实测 · 本机执行输出
  w:majority(只剩 2 个节点在线):成功,耗时 23.5 ms
  w:3 wtimeout=1000:1016 ms 后返回 WriteConcernError code=64: waiting for replication timed out
  但 w:3 那条文档已经写进了 primary:count({k: "w3"}) = 1

剩 2 个节点时 w:majority 仍成功;w:3 等到 wtimeout 返回 code 64 的 WriteConcernError,但文档已经在 primary 上了——写关注错误不等于写入失败。

只剩一个节点

实测 · 本机执行输出
  只剩 1 个节点在线:isWritablePrimary = False,secondary = True
  向它写入:NotPrimaryError: not primary, full error: {'topologyVersion': {'processId': ObjectId('6acc4c1e275f45487358a

primary 看不到多数就降级成 secondary,继续写会得到 NotPrimaryError。

w:0

实测 · 本机执行输出
  w:0 重复插入 _id:1:没有抛异常(服务端没把错误告诉客户端)
  w:1 重复插入 _id:1:DuplicateKeyError
  t5 里实际文档数 1

不要求确认,重复键等错误不会报告给客户端。

设置位置

实测 · 本机执行输出
  连接串 w=2:client.write_concern = {'w': 2}
  集合上 with_options(write_concern=WriteConcern(w=1)):{'w': 1}
  # mongosh:单次操作指定
  test> db.t.insertOne({x: 1}, {writeConcern: {w: "majority", wtimeout: 5000}}).acknowledged
  true

连接串、集合、单次操作都可以指定写关注,单次操作的优先级最高。

分步演示

写关注的耗时
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / MongoDB 9.0.2(Homebrew 的 mongod、mongos)/ mongosh 2.12.0 / pymongo 4.18.3;每个实验在临时目录里起全新的 mongod(独立 dbpath,端口 9900 以上,只监听 127.0.0.1,WiredTiger 缓存 0.25 GB),需要副本集或分片集群时在本机起多个进程;命令输出来自真实的 mongosh,批量写入、计时与多线程用 pymongo;计时用 time.perf_counter,数字每次运行会有小幅抖动,ObjectId、时间戳等每次运行都不同。3 个 mongod 进程组成副本集(oplog 128 MB),全部在本机,没有网络延迟;延迟数字是本机回环上的结果
    • 没有验证:跨机器、跨机房的网络延迟下 w:majority 的耗时;writeConcernMajorityJournalDefault 设为 false 时的行为;带仲裁节点的副本集(后面单独一篇);w:majority 的写入在 primary 切换后是否会回滚(后面 rollback 一篇);分片集群里的 w:majority
    京ICP备2026067502号-1京公网安备11010502063487号