MongoDB复制集的运维工作中,了解每个节点上复制操作的执行情况非常重要。$opcountersRepl是serverStatus输出中的一个统计字段,它记录了当前节点作为复制成员,在应用oplog(重放主节点操作)时执行的各类操作计数。借助聚合管道中的$serverStatus阶段,我们可以把这些计数器数据直接拿出来做过滤、投影和二次计算,配合监控体系非常方便。这篇文章就来详细聊聊它的含义、获取方式以及实际应用。

$opcountersRepl到底统计了什么
要理解$opcountersRepl,先要明白复制集的工作机制。主节点接收客户端写入后,会把操作记录到oplog(操作日志)中,从节点持续拉取oplog并在本地重放这些操作。$opcountersRepl统计的就是这个"重放"过程中各类操作执行的次数,也就是说,它反映的是节点作为复制角色时的活动量,而不是客户端直接触发的操作。
具体来说,$opcountersRepl包含以下几个子字段:insert、query、update、delete、getmore、command,分别对应复制上下文中执行的新增、查询、更新、删除、获取更多游标数据以及命令操作的累计次数。注意在4.0版本之前,这个字段还有一个opReplCount之类的汇总概念,而新版本中直接以各操作类型分别计数。
还有一个容易混淆的点:$opcountersRepl和$opcounters的区别。$opcounters统计的是节点接收到的客户端请求操作,而$opcountersRepl统计的是节点重放oplog的操作。对于主节点来说,写入操作由客户端触发,所以主要反映在$opcounters里;对于从节点,所有写入都来自oplog重放,所以体现在$opcountersRepl里。理解了这一点,在分析各节点负载时才不会张冠李戴。
通过聚合管道获取复制操作计数器
从MongoDB 4.0开始,serverStatus命令可以作为聚合管道的一个阶段使用,语法上是在db.aggregate()中传入{ $serverStatus: {} }。这样做的好处是可以在同一条管道中继续追加$project、$match等阶段,只提取我们关心的字段,输出结果干净利落。
下面是一条完整的示例命令:
db.aggregate([
{
$serverStatus: {}
},
{
$project: {
opcountersRepl: 1,
_id: 0
}
}
])返回结果大致如下:
{
"opcountersRepl" : {
"insert" : NumberLong(125430),
"query" : NumberLong(102),
"update" : NumberLong(88450),
"delete" : NumberLong(1230),
"getmore" : NumberLong(15),
"command" : NumberLong(0)
}
}如果只关心某几个操作类型,可以在$project阶段做更细粒度的投影,比如只取insert和update:
db.aggregate([
{ $serverStatus: {} },
{
$project: {
_id: 0,
"replInserts": "$opcountersRepl.insert",
"replUpdates": "$opcountersRepl.update"
}
}
])需要说明的是,$serverStatus阶段需要在admin数据库上执行,或者当前用户具备相应的权限。如果在业务库上直接执行报权限错误,可以先执行use admin切换数据库再运行。
结合应用场景做监控与性能排查
单独看一组累计数字意义有限,$opcountersRepl的价值主要体现在趋势分析和对比上。一个典型的场景是评估从节点的写入压力:如果业务写入以更新为主,你会发现从节点的opcountersRepl.update增长速度与主节点的opcounters.update基本同步,说明复制链路健康;如果从节点计数明显滞后,就可能存在oplog应用积压,需要进一步查看replication的滞后指标。
另一个场景是排查索引缺失导致的复制放大。有些更新操作在没有合适索引的情况下,从节点重放时需要做全表扫描式的定位,表现为opcountersRepl.query异常增长。注意这里有个细节:从节点重放写操作时,查询定位的次数也会体现在相关计数中,如果发现从节点的query计数远超预期,就应该检查对应集合的索引是否和主节点一致。
在实际监控中,推荐的做法是定时采集差值而非直接存累计值。比如每60秒执行一次聚合查询,计算前后两次的增量,再除以时间间隔得到每秒复制操作速率。下面是一个用mongosh脚本实现差值采集的简单示例:
// 采集复制操作速率的简化示例
let prev = null;
setInterval(function () {
db.getSiblingDB("admin").aggregate([
{ $serverStatus: {} },
{ $project: { _id: 0, opcountersRepl: 1 } }
]).forEach(function (doc) {
if (prev) {
let delta = doc.opcountersRepl.insert - prev.insert;
print("每秒复制插入速率约: " + delta / 60);
}
prev = doc.opcountersRepl;
});
}, 60000);此外还有两点使用提醒。第一,这些计数器从进程启动开始累计,重启mongod后会归零,做监控时要把重启事件纳入考虑,否则会出现负增量或突变。第二,如果部署了链式复制,某些从节点的主同步源可能是另一个从节点,此时它的opcountersRepl依然反映的是本节点重放oplog的操作量,分析拓扑时要注意辨别数据流向。
总的来说,$opcountersRepl配合聚合管道的$serverStatus阶段,为我们提供了一条轻量、灵活的路径去观察复制集内部的操作流转。把它接入定时采集和告警体系,再结合oplog窗口、复制延迟等指标一起分析,就能对复制集的健康状态形成比较完整的判断。
MongoDB聚合管道opcountersRepl修改时间:2026-09-06 00:30:42