MongoDB事务开发之写操作事务writeConcern
一、什么是writeConcern ?
writeConcern 决定一个写操作落到多少个节点上才算成功。writeConcern 的取值包括:
- 0:发起写操作,不关心是否成功;
- 1~集群最大数据节点数:写操作需要被复制到指定节点数才算成功;
- majority:写操作需要被复制到大多数节点上才算成功。发起写操作的程序将阻塞到写操作到达指定的节点数为止。
1.1 默认行为
- 3 节点复制集不作任何特别设定(默认值):
1.2 w: "majority"
- 大多数节点确认模式
1.3 w: "all"
1.4 j: true
writeConcern 可以决定写操作到达多少个节点才算成功,journal则定义如何才算成功。取值包括:
- true: 写操作落到 journal(日志)文件中才算成功;
- false: 写操作到达内存即算作成功。
二、writeConcern 的意义
对于5个节点的复制集来说,写操作落到多少个节点上才算是安全的?
- 1
- 2
- 3 ✓
- 4 ✓
- 5 ✓
- majority ✓
三、writeConcern 实验
3.1 在复制集测试writeConcern参数
rs0:PRIMARY> db.test.insert( {count: 1}) # 默认 WriteResult({ "nInserted" : 1 }) rs0:PRIMARY> db.test.insert( {count: 1}, {writeConcern: {w: "majority"}}) # 大多数节点 WriteResult({ "nInserted" : 1 }) rs0:PRIMARY> db.test.insert( {count: 1}, {writeConcern: {w: 3 }}) # 三个节点 WriteResult({ "nInserted" : 1 }) rs0:PRIMARY> db.test.insert( {count: 1}, {writeConcern: {w: 4 }}) # 由于集群只有三个节点,所以当要求数据落到4个节点才返回成功时,会报错 WriteResult({ "nInserted" : 1, "writeConcernError" : { "code" : 100, "codeName" : "UnsatisfiableWriteConcern", "errmsg" : "Not enough data-bearing nodes" } }) # 查看插入成功记录 rs0:PRIMARY> db.test.find() { "_id" : ObjectId("60cefe0e651d9ab31c945d0c"), "count" : 1 } { "_id" : ObjectId("60cefe16651d9ab31c945d0d"), "count" : 1 } { "_id" : ObjectId("60cefe1c651d9ab31c945d0e"), "count" : 1 } { "_id" : ObjectId("60cefe23651d9ab31c945d0f"), "count" : 1 }
3.2 配置延迟节点,模拟网络延迟(复制延迟)
(1)将副本集节点配置存入conf参数
rs0:PRIMARY> conf=rs.conf() { "_id" : "rs0", "version" : 3, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "10-27-0-224:28017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "10-27-0-224:28018", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "10-27-0-224:28019", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("60ce02f5209133abd12c1175") } }
(2)查看获取的属组信息
rs0:PRIMARY> conf.members [ { "_id" : 0, "host" : "10-27-0-224:28017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "10-27-0-224:28018", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "10-27-0-224:28019", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ]
(3)设置延迟节点
rs0:PRIMARY> conf.members[2].slaveDelay = 5 # 设置第三个节点延迟5s 5 rs0:PRIMARY> conf.members[2].priority = 0 # 取消第第三个节点参与选举的权利 0
(4)保存配置
rs0:PRIMARY> rs.reconfig(conf) { "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1624178758, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1624178758, 1) }
(5)观察复制延迟下的写入,以及timeout参数
rs0:PRIMARY> db.test.insert( {count: 1}, {writeConcern: {w: 3}}) rs0:PRIMARY> db.test.insert( {count: 1}, {writeConcern: {w: 3, wtimeout:3000 }})
四、注意事项
- 虽然多于半数的 writeConcern都是安全的,但通常只会设置majority,因为这是等待写入延迟时间最短的选择;
- 不要设置 writeConcern 等于总节点数,因为一旦有一个节点故障,所有写操作都将失败;
- writeConcern 虽然会增加写操作延迟时间,但并不会显著增加集群压力,因此无论是否等待,写操作最终都会复制到所有节点上。设置 writeConcern 只是让写操作等待复制后再返回而已;
- 应对重要数据应用 {w: “majority”},普通数据可以应用 {w: 1} 以确保最佳性能。
作者:UStarGao
链接:https://www.starcto.com/mongodb/296.html
来源:STARCTO
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
UCloud云平台推荐
随便看看
- 2024-11-19ubuntu容器化部署ffmpeg通过GPU硬件加速处理视频流
- 2021-11-17Docker打包运行中的容器为镜像并Push到UHub
- 2021-09-04跨域访问和防盗链基本原理
- 2021-02-28Linux账户风险和安全策略
- 2021-08-12开源分布式爬虫管理平台Crawlab容器化部署