mongodb支持的writeconncern选项如下
w: <number>,数据写入到number个节点才向用客户端确认
{w: 0} 对客户端的写入不需要发送任何确认,适用于性能要求高,但不关注正确性的场景
{w: 1} 默认的writeconcern,数据写入到primary就向客户端发送确认
{w: "majority"} 数据写入到副本集大多数成员后向客户端发送确认,适用于对数据安全性要求比较高的场景,该选项会降低写入性能
j: <boolean> ,写入操作的journal持久化后才向客户端确认
默认为"{j: false},如果要求primary写入持久化了才向客户端确认,则指定该选项为true
wtimeout: <millseconds>,写入超时时间,仅w的值大于1时有效。
当指定{w: }时,数据需要成功写入number个节点才算成功,如果写入过程中有节点故障,可能导致这个条件一直不能满足,从而一直不能向客户端发送确认结果,针对这种情况,客户端可设置wtimeout选项来指定超时时间,当写入过程持续超过该时间仍未结束,则认为写入失败。
{w: 1}、{j: true}等writeconcern选项很好理解,primary等待条件满足发送确认;但{w: "majority"}则相对复杂些,需要确认数据成功写入到大多数节点才算成功,而mongodb的复制是通过secondary不断拉取oplog并重放来实现的,并不是primary主动将写入同步给secondary,那么primary是如何确认数据已成功写入到大多数节点的?

client向primary发起请求,指定writeconcern为{w: "majority"},primary收到请求,本地写入并记录写请求到oplog,然后等待大多数节点都同步了这条/批oplog(secondary应用完oplog会向主报告最新进度)。
secondary上有单独的线程,当oplog的最新时间戳发生更新时,就会向primary发送replsetupdateposition命令更新自己的oplog时间戳。
当primary发现有足够多的节点oplog时间戳已经满足条件了,向客户端发送确认。
<a href="https://www.aliyun.com/product/mongodb">mongodb云数据库</a>
<a href="https://docs.mongodb.com/manual/reference/command/find/#dbcmd.find">find command</a>
<a href="https://docs.mongodb.com/manual/reference/write-concern/">writeconcern</a>