一、什么是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} 以确保最佳性能。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/128116.html
摘要:介绍事务和副本集副本集是的一种主副节点架构,它使数据得到最大的可用性,避免单点故障引起的整个服务不能访问的情况的发生。在事务中执行的数据操作是对外隔离的,也就是说事务中的操作是原子性的。中止当前的事务,并将事务中执行过的数据修改回滚。 前言 相信使用过主流的关系型数据库的朋友对事务(Transactions)不会太陌生,它可以让我们把对多张表的多次数据库操作整合为一次原子操作,这在高并...
摘要:官网中,对单文档的操作是原子性的。因此建议使用嵌入式文档来实现事务需求,而不是规范化的跨文档设计。所以开始提供了对副本集多文档事务的支持,注意是副本集,也就是说单是不生效的。上面创建的中的上添加了提供的注解,所以的事务可以和的事务统一管理。 官网:mongoDB中,对单文档的操作是原子性的。例如insertOne,updateOne等操作。因此建议使用嵌入式文档来实现事务需求,而不是规...
摘要:参考链接官方关于事务的介绍中文社区关于的介绍如果不想进行第二步,可以直接为你创建一个新的复制集我只是个前端啊,为什么要这么折磨我 主管前几天发现mongoDB已经升级到4.0了,迫不及待得让我实现他期待已久的事务回滚,发现还是有很多坑啊!下面是我将已有的本地mongoDB升级到支持事务回滚的历程,分享出来,有错误的地方欢迎指正!以mac为例哈 部署mongodb事务回滚 1.准备工作 ...
摘要:原文保持更新及修正基于的客户端配置选项,其它驱动大同小异。连接池中连接的最大使用寿命毫秒。设置该选项后,客户端将进行以下行为以副本集模式连接,并根据给定的服务器发现副本集的所有成员。该选项可以和配合使用。编解码器用于对进行编码和解码。 原文保持更新及BUG修正:http://kweny.io/mongodb-clien... 基于 MongoDB Java Driver 3.8.1 ...
摘要:布尔类型,表示文档是否按照有序或者无序插入,默认是返回参数返回了含有操作状态的对象插入文档成功返回如下对象字段指明了插入文档的总数如果该操作遇到了错误对象将包含该错误信息例子四其它可以向集合中添加文档的方法和选项一起使用的。 上一节介绍了MongoDB的基本的命令,以及结构的了解,这一节的主题是介绍一下MongoDB的插入文档的操作的基础命令的使用,MongoDB当中文档的数据结构和j...
阅读 1279·2024-02-01 10:43
阅读 366·2024-01-31 14:58
阅读 432·2024-01-31 14:54
阅读 814·2024-01-29 17:11
阅读 2200·2024-01-25 14:55
阅读 1477·2023-06-02 13:36
阅读 2077·2023-05-23 10:26
阅读 468·2023-05-23 10:25