什么是writeConcern
writeConcern决定一个写操作落到多少个节点上才算成功。writeConcern的取值包括:
- 0:发起写操作,不关心是否成功;
- 1~集群最大数据节点数,写操作需要被复制到指定节点数才算成功
- majority:写操作需要被复制到大多数节点才算成功。 发起写操作的程序将阻塞到写操作到达指定的节点数为止
默认行为:
3节点复制集不做任何特定设置(默认值)时的操作如下图所示:
大多数节点确认模式:
`w:“majority”
当写的操作被大多数节点写入成功后才返回
全部节点确认模式
w:"all"
设置后需要当所有的节点都将数据写入后才返回
journal
writeConcern可以决定写操作到达多少个节点才算成功,journal则定义如何才算成功。取值包括:
- true:写操作落到journal文件中才算成功
- false:写操作到达内存即算作成功
实验
在复制集测试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}
以确保最佳性能