mongo-写操作事务

发布于 — 2020 年 04 月 14 日
#Mongo

什么是writeConcern

writeConcern决定一个写操作落到多少个节点上才算成功。writeConcern的取值包括:

  • 0:发起写操作,不关心是否成功;
  • 1~集群最大数据节点数,写操作需要被复制到指定节点数才算成功
  • majority:写操作需要被复制到大多数节点才算成功。 发起写操作的程序将阻塞到写操作到达指定的节点数为止

默认行为:

3节点复制集不做任何特定设置(默认值)时的操作如下图所示:

https://raw.githubusercontent.com/liunaijie/images/master/1585393042221.jpg

大多数节点确认模式:

`w:“majority”

https://raw.githubusercontent.com/liunaijie/images/master/1585393318539.jpg

当写的操作被大多数节点写入成功后才返回

全部节点确认模式

w:"all" 设置后需要当所有的节点都将数据写入后才返回

journal

writeConcern可以决定写操作到达多少个节点才算成功,journal则定义如何才算成功。取值包括:

  • true:写操作落到journal文件中才算成功
  • false:写操作到达内存即算作成功

https://raw.githubusercontent.com/liunaijie/images/master/1585393755601.jpg

实验

在复制集测试writeConcern参数

db.test.insert({count:1,{writeConcern:{w:"majority"}}})
db.test.insert({count:1,{writeConcern:{w:"3"}}})
db.test.insert({count:1,{writeConcern:{w:"4"}}})

正常情况下,是可以正常返回的,可以手动修改配置,模拟延迟环境。 修改复制延迟参数:

conf=rs.conf()
conf.members[i].slaveDelay=5 # 将第i个节点设置5秒的复制延迟
conf.members[i].priority=0 # 由于延迟所以不能设置为主节点
rs.reconfig(conf)  # 启用配置

设置超过延迟时间后失败:

db.test.inser({count:3},{writeConcern:{w:"majority",wtimeout:3000}}) #当大多数节点写入成功就算成功,超过3秒后如果未返回则失败

注意事项: 我们假设使用上面的配置,对节点启用5秒的延迟写入,并且等待超时时间为3秒,那么会返回下面的信息:

WriteResult({
    "nInserted":1,
    "writeConcernError" :{
        ...
    }
})

可以看到上面有个属性nInserted,这个属性表示已经成功写入了多个个节点,这里表示已经成功写入了1个节点,并不是全部的节点都没有这个数据。所以这是需要注意的地方

注意事项

  • 虽然多于办事的writeConcern都是安全的,但通常只会设置majority,这是因为等待写入延迟时间最短的选择
  • 不要将writeConcern等于总节点数,因为一旦有一个节点故障,所有写操作都将失败
  • writeConcern虽然会增加写操作延迟时间,但并不会显著增加集群压力,因此无论是否等待,写操作最终都会复制到所有节点上。设置writeConcern只是让写操作复制后再返回而已
  • 应对重要数据应用{w:"majority"},普通数据可以应用{w:1}以确保最佳性能