前段时间杂七杂八的看了mysql和es的知识点,好久没更简书了,今天继续mongo的知识回顾
之前提到,mongodb的一致性需要借助writeConcern和readConcern的帮忙,且mongo的一切事务都需要手动配置开启,默认事务是没有开启的,为了访问的速度
首先什么是 writeConcern ?
writeConcern 决定一个写操作落到多少个节点上才算成功。
write concern支持3个配置项:
{ w: <value>, j: <boolean>, wtimeout: <number> }
w的取值包括:
• 0:发起写操作,不关心是否成功;
• 1~集群最大数据节点数:写操作需要被复制到指定节点数才算成功;
• majority:写操作需要被复制到大多数节点上才算成功。
发起写操作的程序将阻塞到写操作到达指定的节点数为止
以三个节点的集群为例子
当配置majority时,大多数节点为2,Primary感知到两个节点被写入完成时就代表成功写入
majority.png
j,该参数表示是否写操作要进行journal持久化之后才向用户确认;
{j: true} 要求primary写操作进行了journal持久化之后才向用户确认;
{j: false} 要求写操作已经在journal缓存中即可向用户确认;journal后续会将持久化到磁盘,默认是100ms;
有点类似于mysql的双1配置了,数据必定落盘;
为什么mysql要双一才能保证事务一致性:
redo没有及时刷盘,binlog刷盘了,之后瞬间数据库所在主机掉电,主机重启,MySQL重启以后,这个事务会丢失;这里会引起日志和数据不一致。
wtimeout,该参数表示写入超时时间,w大于1时有效;当w大于1时,写操作需要成功写入若干个节点才算成功,如果写入过程中节点有故障,导致写操作迟迟不能满足w要求,也就一直不能向用户返回确认结果,为了防止这种情况,用户可以设置wtimeout来指定超时时间,写入过程持续超过该时间仍未结束,则认为写入失败。
虽然多于半数的 writeConcern 都是安全的,但通常只会设置 majority,因为这是
等待写入延迟时间最短的选择;
• 不要设置 writeConcern 等于总节点数,因为一旦有一个节点故障,所有写操作都
将失败;
• writeConcern 虽然会增加写操作延迟时间,但并不会显著增加集群压力,因此无论
是否等待,写操作最终都会复制到所有节点上。设置 writeConcern 只是让写操作
等待复制后再返回而已;
• 应对重要数据应用 {w: “majority”},普通数据可以应用 {w: 1} 以确保最佳性能。
什么是 readPreference ?
readPreference 决定使用哪一个节点来满足正在发起的读请求
可选项有
primary: 只选择主节点;
primaryPreferred:优先选择主节点,如
果不可用则选择从节点;
secondary:只选择从节点;
secondaryPreferred:优先选择从节点,如果从节点不可用则选择主节点;
nearest:选择最近的节点;
使用格式为db.collection.find({}).readPref( “secondary” )
若是想控制多个节点可以配合tag使用,具体参考文档,本人暂时这部分没实践过
https://docs.mongodb.com/manual/core/read-preference/
什么是 readConcern?
在 readPreference 选择了指定的节点后,readConcern 决定这个节点上的数据哪些
是可读的,类似于关系数据库的隔离级别
格式为:readConcern: { level: <level> }
可选值包括:
• available:读取所有可用的数据;
• local:读取所有可用且属于当前分片的数据;
• majority:读取在大多数节点上提交完成的数据;
• linearizable:可线性化读取文档;
• snapshot:读取最近快照中的数据;
极客时间中available与local的区别
极客时间.png
注意事项:
1,虽然看上去总是应该选择 local,但毕竟对结果集进行过滤会造成额外消耗。在一些无关紧要的场景(例如统计)下,也可以考虑 available;
2,MongoDB <=3.6 不支持对从节点使用 {readConcern: "local"};
3,从主节点读取数据时默认 readConcern 是 local,从从节点读取数据时默认readConcern 是 available(向前兼容原因)
问题:{readConcern: “majority”}可以避免脏读吗?
只能极大程度的避免,所谓的脏读可能出现的原因是使用的writeConcern,数据写到从节点后被读取,但是由于系统故障导致最终没写入成功,读取的数据就是脏读了。而{readConcern: “majority”}是从绝大多数拥有数据的节点读取,因此能大程度避免脏读,但是可能出现主节点宕机,或者readConcern写到所有节点才算成功的现象,所以不能完全避免。
网友评论