文章来源:Nodejs技术栈 / 原文链接 MongoDB 单文档原生支持原子性,也具备事务的特性,但是我们说起事务,通常是指在多文档中的实现,因此,MongoDB 在 4.0 版本支持了多文档事务,4.0 对应于复制集的多表、多行,后续又在 4.2 版本支持了分片集的多表、多行事务操作。 事务四大特性
Read Concern/Write Concern/Read Preference在事务操作中会分别使用到 readConcern、writeConcern、readPreference 这几个选项,用于控制 Session 的行为,下面分别予以介绍。 事务和 Write Concern事务使用事务级别的 writeConcern 来提交写操作,决定一个事务的写入成功与否要看 writeConcern 选项设置了几个节点,默认情况下为 1。 几个选项值:
设置示例:writeConcern: { JavaScript 使用示例:
建议对于重要数据可以应用 w:'majority' 设置,普通数据 w:1 设置则可以保证性能最佳,w 设置的节点数越多,等待的延迟也就越大,如果 w 等于总节点数,一旦其中某个节点出现故障就会导致整个写入失败,也是有风险的。 docs.mongodb.com/manual/reference/write-concern/?spm=a2c4e.10696291.0.0.68d519a4ob3Yya 事务和 Read Preference在一个事务操作中使用事务级别的 readPreference 来决定读取时从哪个节点读取。可方便的实现读写分离、就近读取策略。 可选值以下 5 个:
场景选择
使用示例
mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017,mongodb2.example.com:27017/admin?replicaSet=myRepl&readPreference=secondary
测试时可借助 db.fsyncUnlock() 对从节点锁定,仅主节点写入数据。 docs.mongodb.com/manual/core/read-preference/#replica-set-read-preference 事务和 Read ConcernMongoDB 3.2 引入了 readConcern 来决定读取的策略,但是与 readPreference 不同,readPreference 决定从哪个节点读取,readConcern 决定该节点的哪些数据是可读的。主要保证事务中的隔离性,避免脏读。 可选值
更新配置项在启动 Mongod 实例时,指定 --enableMajorityReadConcern 选项或在配置文件中配置 enableMajorityReadConcern=true 重新启动实例,Mongo shell 登陆实例,使用
使用示例db.user.find().readConcern('majority') readConcern 总结MongoDB 的 readConcern 默认情况下是脏读,例如,用户在主节点读取一条数据之后,该节点未将数据同步至其它从节点,就因为异常挂掉了,待主节点恢复之后,将未同步至其它节点的数据进行回滚,就出现了脏读。 readConcern 级别的 majority 可以保证读到的数据已经落入到大多数节点。所以说保证了事务的隔离性,所谓隔离性也是指事务内的操作,事务外是看不见的。 readConcern 参考
读写分离实践一个典型的应用场景是用户写入订单数据(数据写入 Primary),立即调用查询接口,由于采用读写分离模式,链接字符串设置 readPreference=secondaryPreferred 订单写入主节点之后并不能保证数据立即同步到从节点,若此时直接由从节点读取数据, 偶尔会出现订单数据无法找到,用户就会感觉很奇怪,明明下了订单,却又查找不到,造成一些异常订单。 一种导致下单之后再次查找丢失订单的的写法如下:
解决方法一: 设置 readPreference=primary,将复制集的节点读取由从节点转换为主节点。 这种方式一个缺点是数据量大了之后会增加主节点的压力,也就没有了主从分离的模式。 解决方法二: 使用 writeConcern、readConcern 组合来解决,即保证读写分离模式,也保证了数据的一致性。 // 写入时保证大多数节点写入成功 |
|