MongoDB的WriteConcern
文章目录
WriteConcern
write Concern 決定一个写操作落到多少个节点上オ算成功。包括以下3个字段:
{ w: <value>, j: <boolean>, wtimeout: <number> }
MongoDB支持的WriteConncern选项如下
w选项
w: 数据写入到number个节点才向用客户端确认
{w: 0}
对客户端的写入不需要发送任何确认,适用于性能要求高,但不关注正确性的场景
{w: 1}
默认的writeConcern,数据写入到Primary就向客户端发送确认.
丢数据的情景在极端情况下是有可能发生的:
- 写入x=1,primary返回给客户端完成.
- primary瞬间crash,甚至没时间写入rollback日志,secondry1和secondry2没时间同步数据.
- 从secondry1和secondry2中选出primory,任意一个节点都没有x=1.
如果不希望丢数据,可以使用“majority”选项.
{w:1~maxnumbers}
写操作需要被复制到指定节点数才算成功;发起写操作的程序将阻塞到写操作到达指定的节点数为止.
{w: “majority”}
数据写入到副本集大多数成员后向客户端发送确认,适用于对数据安全性要求比较高的场景,该选项会降低写入性能
x=1写入primary后,写进程进入等待,每有一个secondry从primary复制完成x=1后,向primary发送ack信号,当primary收到大多数成员的ack响应后,向客户端发送确认.
因为副本集节点为3,只要有2个节点响应,就可以回复成功.
如果primary crash后,secondry1会成为主节点,x=1数据不会丢失.
MongoDB的复制是通过Secondary不断拉取oplog并重放来实现的,并不是Primary主动将写入同步给Secondary,那么Primary是如何确认数据已成功写入到大多数节点的?
http://77g6ez.com1.z0.glb.clouddn.com/majority.png
- Client向Primary发起请求,指定writeConcern为{w: “majority”},Primary收到请求,本地写入并记录写请求到oplog,然后等待大多数节点都同步了这条/批oplog(Secondary应用完oplog会向主报告最新进度)。
- Secondary拉取到Primary上新写入的oplog,本地重放并记录oplog。为了让Secondary能在第一时间内拉取到主上的oplog,find命令支持一个awaitData的选项,当find没有任何符合条件的文档时,并不立即返回,而是等待最多maxTimeMS(默认为2s)时间看是否有新的符合条件的数据,如果有就返回;所以当新写入oplog时,备立马能获取到新的oplog。
- Secondary上有单独的线程,当oplog的最新时间戳发生更新时,就会向Primary发送replSetUpdatePosition命令更新自己的oplog时间戳。
- 当Primary发现有足够多的节点oplog时间戳已经满足条件了,向客户端发送确认。
{w:“all”}
写操作需要被复制到全部节点才算成功.只要有一个节点没反馈,写操作就无法完成.
这是最安全的做法,但如果一个节点故障,数据库就无法写入.
j选项
Write Concern 可以决定写操作到达多少个节点才算成功,journal 则定义如何才算成功。取值包括:
- true:写操作落到 journal 文件中才算成功
- false:默认取值,写操作到达内存即算作成功。
x=1进入primary后,primary将日志写到journal 文件中才返回成功.
wtimeout选项
wtimeout: 写入超时时间,仅w的值大于1时有效。
当指定{w: }时,数据需要成功写入number个节点才算成功,如果写入过程中有节点故障,可能导致这个条件一直不能满足,从而一直不能向客户端发送确认结果,针对这种情况,客户端可设置wtimeout选项来指定超时时间,当写入过程持续超过该时间仍未结束,则认为写入失败。
注意事项
-
虽然多于半数的 write Concern 都是安全的,但通常只会设置 majority,因为这是等待写入延迟时间最短的选择
-
不要设置 writeconcern 等于总节点数,因为一旦有一个节点故障,所有写操作都将失败
-
write Concern 虽然会增加写操作延迟时间,但并不会显著增加集群压力,因此无论是否等待,写操作最终都会复制到所有节点上。设置 write Concern 只是让写操作等待复制后再返回而已
-
应对重要数据应用{w:“majority"},普通数据可以应用{w: }以确保最佳性能
文章作者 Forz
上次更新 2020-03-26