MongoDB学习笔记之WriteConcern
WriteConcern:
转载:MongoDB WriteConcern(写关注)机制
青春奇妙物语
MongoDB部署模式
MongoDB的部署模式有三种:第⼀种是单机模式(开发测试);第⼆种是⾼可⽤复制集;第三种是可扩展分⽚集群。如下图所⽰。
知道了MongoDB⼏种常⽤的部署模式之后,接下来我们看看每种部署模式的写操作过程。
MongoDB单点写操作
从上图可以看出,其中primary是MongoDB的⼀个实例,⾥⾯有两个内存区域,⼀个是Data Buffer(数据缓冲)、⼀个是Journal Buffer(⽇志缓冲)。这两个内存区域分别对应物理⽂件Data File和Journal Fi
le。
当数据写⼊进来时,就会出现如下执⾏顺序:
1)客户端的数据进来;
五年级下册人教版
2)数据操作写⼊到⽇志缓冲;
3)数据写⼊到数据缓冲;
4)返回操作结果到客户端(异步);
5)后台线程进⾏⽇志缓冲中的数据刷盘,⾮常频繁(默认100)毫秒,也可⾃⾏设置(30-60);
6)后台线程进⾏数据缓冲中的数据刷盘,默认是60秒;
MongoDB复制集写操作
复制集也是MongoDB最常见的⼀种部署模式,如果启⽤复制集的话,在内存中会多⼀个OPLOG区域,是在节点之间进⾏同步的⼀个⼿段,它会把操作⽇志放到OPLOG中来,然后OPLOG会复制到从节点上。从节点接收并执⾏OPLOG中的操作⽇志来达到数据的同步操作。
1) 客户端的数据进来;
2) 数据操作写⼊到⽇志缓冲;
刘强东自述3) 数据写⼊到数据缓冲;
4) 把⽇志缓冲中的操作⽇志放到OPLOG中来;
5) 返回操作结果到客户端(异步);
儿童拉丁舞视频6) 后台线程进⾏OPLOG复制到从节点,这个频率是⾮常⾼的,⽐⽇志刷盘频率还要⾼,从节点会⼀直监听主节点,OPLOG⼀有变化就会进⾏复制操作;
7) 后台线程进⾏⽇志缓冲中的数据刷盘,⾮常频繁(默认100)毫秒,也可⾃⾏设置(30-60);
8) 后台线程进⾏数据缓冲中的数据刷盘,默认是60秒;
恢复⽇志Journal的作⽤
1)⽤于系统宕机时恢复内存数据(不能像MySQL⼀样可以⽤来恢复历史数据)
2)默认为异步刷盘
3)刷盘间隔,MMAP引擎为30-100ms,Wiredtiger为100MB or checkpoint
4)可使⽤j:1来强制同步刷盘黄玉川煤矿
写关注机制Write Concern的作⽤
1)⽤来指定mongod对写操作的回执⾏为。
2)可在connection level或者写操作level指定。
3) Write conern⽀持以下值。
W: 0 | 1 | N | majority | tag
房贷浮动利率
j:1
wtimeout:millis
1)当w:0为
Unacknowledged
测试(会出现的数据丢失情况)
这⾥写⼀个循环插⼊10条数据,插⼊数据{_id:10,a:i},然后把writeConcern设置为0。根据上图我们可以看到print返回10条插⼊成功的信息,但是我们unt()查看时只有⼀条数据,其余9条虽然没有插⼊成功但是也返回了正确信息(因为第⼀条数据_id:10为唯⼀键,再插⼊同样的数据就⽆法插⼊,两个ID不能相同)。就因为{writeConcern:{w:0}}导致出现异常时并没有返回错误信息给客户端。
2)当w:1为
Acknowledged
测试(会出现的数据丢失情况)
洱海在哪当w:1时,就解决了w:0出现的问题,从上图可以看出第⼀条数据插⼊成功,其余9条数据都会插⼊失败并返回错误信息给客户端。
但是当w:1时mongodb就会在⽇志写完之后返回确定信息,虽然解决了w:0出现的数据丢失问题,但是w:1时如果出现系统崩溃也会导致数据丢失,那就是在⽇志信息还没有刷新到磁盘的那⼀刻发⽣系统宕机,此时内存⽇志的确是写⼊成功了于是mongodb就会返回确定信息。
我们可以通过w:1然后⾼速写⼊数据,然后通过killall -9 mongod来模拟系统崩溃(重启系统时要记住删除数据⽬录下的mongod.lock⽂件,
不然启动起不来),最后检查程序写⼊的数据和实际插⼊的数据(这种情况发⽣⼏率不⼤)。
通过上图可以看出,数据丢失了731条。做上⾯这个实验时在执⾏journaldataloss函数时,需要开启另外⼀个会话⽤来模拟服务器宕机(killall -9 mongod)
针对w:1出现的服务器宕机时数据丢失的问题可以使⽤j:1来解决,j:1做到的是⽇志刷盘之后才会返回确定信息。
1> db.test.validate(true)
函数脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14function journaldataloss(){
var count=0, start = new Date();
try{
var docs=[];
for(var i=0;i<1000;i++) docs.push({a:i});
while(true){
var st.inrt(docs);
count += res.nInrted;
if(count % 100000 == 0) print("inrted "+ count+"time ud: " + (new Date().getTime() - Time()/1000) +" conds");
}
}
catch(error){ print("Total doc inrted successfully:"+ count); }
}
3)当j:1为
Journal
实例(测试会出现的数据丢失情况)
信息检索报告
另⼀种情况
当j:1时可以解决w:1数据丢失的问题,但是随之⽽来的是Mongodb的性能会下降。虽然解决了服务器宕机时数据丢失问题(会丢失60s左右的数据,就是⼀次间隔没有刷新到磁盘的数据)。
但是⽆法解决另外⼀种情况,⽆论是w:1还是j:1都⽆法解决主备置换导致数据丢失的情况。上⾯我们介绍了MongoDB三种部署模式以及每⼀种模式的写操作流程。看下⾯这幅图,
当j:1时可以保证主节点数据的决定安全性,当⽇志落盘之后返回确定信息给客户端,那么接下来就会复制OPLOG到复制集中的从节点如果此时主节点宕机,OPLOG没有复制到从节点并且当主节点宕机后,Mongodb复制集会重新选举台condary为primary。当condary为primary后假设此时原先的primary被恢复了,启动之后成为了condary节点,此时新的primary发现condary有x数据⽽⾃⼰没有,那么此时就会出现数据回滚的情况,condary会把x数据进⾏回滚到⼀个磁盘⽂件上(rollback_db_name),回头需要⼈⼯去处理,从⽤户⾓度出现这也是⼀种数据丢失的情况。那么怎
么解决这种情况呢?就是下⾯我们要提到的w:2/N/majority可以解决这个数据丢失的情况,w:2决定了数据必须复制最少到⼀个从节点上时才会返回确定信息给客户端。
4)当w:2/N/majority replica Acknowledged
显然这种⽅式虽然保证了数据的⼀致性,但是⽆疑会拖慢MongoDB的性能。所以在MongoDB 3.2后官⽅⼜给出了⼀个readconcern机制,具体待研究。
Write concern总结
通过上⾯⼏幅图对Write concern的解释可以看出,这是⼀个对数据安全⾮常重要的参数,不管是开发还是运维⼈员都应该对Write concern机制⾮常了解。对于Write concern来说,级别越⾼数据越安全,但同时性能就会下降,在数据安全跟性能⽅⾯⼀向如此不能兼得。可根据⾃⼰的应⽤场景来决定Write concern的级别(默认是w:1)。其实j:1到不是特别重要,如果你使⽤好的复制集同时数据⼜特别重要的话就可以使⽤w:majority,因为mongodb中复制集的数据往往⽐⽇志跑的更快,也是⼀种更有效的⽅法。下图是对wirte concern的基本总结。