bigywater.tech
MongoDB · 71

stepDown:切主期间读写不可用多久

切主期间读写不可用多久?优雅切主和崩溃切主差多少?调小 electionTimeoutMillis 有用吗?写入会不会丢?这篇用一个持续写入的客户端在 3 节点副本集上量三种切主方式的不可写时间。

0.03 s
replSetStepDown 优雅切主时客户端看到的最大写入间隔
10.83 s
kill -9 primary(默认 electionTimeoutMillis 10 s)时的不可写时间
0 条
三种切主方式下 w:majority 确认写入丢失的条数

三种切主方式

实测 · 本机执行输出
  方式 A:primary 上执行 replSetStepDown(优雅切主,等 secondary 追平)
    retryWrites=True :动作之后的最大间隔 0.03 s(平时的中位数间隔 11 ms);客户端看到的错误 0 个 {};确认写入 2271 条,丢失 0 条
    retryWrites=False:动作之后的最大间隔 0.03 s;客户端看到的错误 0 个 {};确认写入 2201 条,丢失 0 条
  方式 B:kill -9 primary(崩溃,默认 electionTimeoutMillis = 10 s)
    retryWrites=True :动作之后的最大间隔 10.83 s(平时 12 ms);错误 0 个 {};确认写入 1466 条,丢失 0 条
  方式 C:同样 kill -9,但把 electionTimeoutMillis 调成 4000(必须大于心跳间隔 2000)
    retryWrites=True :动作之后的最大间隔 4.19 s(平时 12 ms);错误 0 个 {};确认写入 1122 条,丢失 0 条

优雅切主(replSetStepDown)让 primary 等 secondary 追平后让位,不可写时间只有约 30 ms;kill -9 后 secondary 要等 electionTimeoutMillis(默认 10 秒)才发起选举,不可写时间约 10.8 秒;调到 4 秒则约 4.2 秒。retryWrites 的驱动等到新 primary 出现后重试,客户端没有看到错误,三种方式下 w:majority 确认的写入都没有丢失。

汇总与取舍

实测 · 本机执行输出
  方式                                         不可写时间
  replSetStepDown(优雅)                       0.03 s
  kill -9,electionTimeoutMillis 10 s       10.83 s
  kill -9,electionTimeoutMillis 4 s         4.19 s

0.03 s、4.19 s、10.83 s。electionTimeoutMillis 越小崩溃切主越快,但必须大于心跳间隔(默认 2 秒),调得太小会增加误判。

切主期间的读

实测 · 本机执行输出
  primary 被 kill 后的 14 秒里,两个线程每 0.2 秒各读一次:
    secondary 读偏好:69 次读,失败 0 次;单次读的最大耗时 5 ms;耗时超过 1 s 的读有 0 次(最长的一次在 kill 后 0.0 s 开始)
    primary 读偏好:  18 次读,失败 0 次;单次读的最大耗时 10465 ms;耗时超过 1 s 的读有 1 次(最长的一次在 kill 后 0.0 s 开始)

secondary 读偏好的读不受影响;primary 读偏好的读会阻塞到新 primary 出现(这里一次读阻塞了 10.5 秒)。

分步演示

切主期间的不可用时间
本步的对象

    本文用到的工具与边界

    • 本机 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 副本集,本机回环(无网络分区);写入间隔 5 ms、w:majority;kill 与 stepDown 在启动 3 秒后执行
    • 没有验证:graceful stepDown 时 retryWrites=False 也没有看到错误的原因(只观察到现象);网络分区造成的切主(心跳超时的检测时间更复杂);priority 不同时的选举;catch-up 阶段(新 primary 追赶旧 primary 未复制的写入);大事务或长查询存在时 stepDown 的等待与强制关闭连接
    京ICP备2026067502号-1京公网安备11010502063487号