http://liyanblog.cn/李岩的博客 李岩 java lucene 搜索 nosql hadoop 博客 mongodb, Nosql2024-03-19T10:22:31+08:00李岩的博客Mongodb复制集中一个mongod挂掉后机器起不来,处理方法savagertnullhttp://liyanblog.cn/articles/2017/11/17/1510895267811.html2017-11-17T13:07:47+08:00<p>199宕机。数据无法恢复。<br />1.将同是shard2的201上的数copy过来。copy之前先停止更新数据。<br />2.找到剩下的两台机器那个是PRIMARY。在PRIMARY上执行如下操作。<br />[liyan@cnews197 ~]$ cd /data/support/mongodb-2.0.2/bin<br />[liyan@cnews197 bin]$ ./mongo -port 15552<br />MongoDB shell version: 2.0.2<br />connecting to: 127.0.0.1:15552/test<br />PRIMARY> rs.status() <br />{<br /> "set" : "shard2",<br /> "date" : ISODate("2017-11-15T08:51:32Z"),<br /> "myState" : 1,<br /> "members" : [<br /> {<br /> "_id" : 0,<br /> "name" : "10.70.56.199:15552",<br /> "health" : 0,<br /> "state" : 8,<br /> "stateStr" : "(not reachable/healthy)",<br /> "uptime" : 0,<br /> "optime" : {<br /> "t" : 1510342250000,<br /> "i" : 1<br /> },<br /> "optimeDate" : ISODate("2017-11-10T19:30:50Z"),<br /> "lastHeartbeat" : ISODate("2017-11-10T19:31:16Z"),<br /> "pingMs" : 0,<br /> "errmsg" : "socket exception"<br /> },<br /> {<br /> "_id" : 1,<br /> "name" : "10.70.56.201:15552",<br /> "health" : 1,<br /> "state" : 2,<br /> "stateStr" : "SECONDARY",<br /> "uptime" : 88,<br /> "optime" : {<br /> "t" : 1510735865000,<br /> "i" : 1<br /> },<br /> "optimeDate" : ISODate("2017-11-15T08:51:05Z"),<br /> "lastHeartbeat" : ISODate("2017-11-15T08:51:30Z"),<br /> "pingMs" : 0<br /> },<br /> {<br /> "_id" : 2,<br /> "name" : "10.70.56.197:15552",<br /> "health" : 1,<br /> "state" : 1,<br /> "stateStr" : "PRIMARY",<br /> "optime" : {<br /> "t" : 1510735865000,<br /> "i" : 1<br /> },<br /> "optimeDate" : ISODate("2017-11-15T08:51:05Z"),<br /> "self" : true<br /> }<br /> ],<br /> "ok" : 1<br />}<br />PRIMARY> rs.remove('10.70.56.199:15552')// 删除旧的mongod<br />Wed Nov 15 16:53:57 DBClientCursor::init call() failed<br />Wed Nov 15 16:53:57 query failed : admin.$cmd { replSetReconfig: { _id: "shard2", version: 2, members: [ { _id: 1, host: "10.70.56.201:15552" }, { _id: 2, host: "10.70.56.197:15552" } ] } } to: 127.0.0.1:15552<br />Wed Nov 15 16:53:57 Error: error doing query: failed shell/collection.js:151<br />Wed Nov 15 16:53:57 trying reconnect to 127.0.0.1:15552<br />Wed Nov 15 16:53:57 reconnect 127.0.0.1:15552 ok<br /> <br />PRIMARY> rs.status() //查看结果<br />{<br /> "set" : "shard2",<br /> "date" : ISODate("2017-11-15T08:54:07Z"),<br /> "myState" : 1,<br /> "members" : [<br /> {<br /> "_id" : 1,<br /> "name" : "10.70.56.201:15552",<br /> "health" : 1,<br /> "state" : 2,<br /> "stateStr" : "SECONDARY",<br /> "uptime" : 8,<br /> "optime" : {<br /> "t" : 1510736036000,<br /> "i" : 1<br /> },<br /> "optimeDate" : ISODate("2017-11-15T08:53:56Z"),<br /> "lastHeartbeat" : ISODate("2017-11-15T08:54:05Z"),<br /> "pingMs" : 0,<br /> "errmsg" : "syncThread: 10278 dbclient error communicating with server: 10.70.56.197:15552"<br /> },<br /> {<br /> "_id" : 2,<br /> "name" : "10.70.56.197:15552",<br /> "health" : 1,<br /> "state" : 1,<br /> "stateStr" : "PRIMARY",<br /> "optime" : {<br /> "t" : 1510736037000,<br /> "i" : 1<br /> },<br /> "optimeDate" : ISODate("2017-11-15T08:53:57Z"),<br /> "self" : true<br /> }<br /> ],<br /> "ok" : 1<br />}<br />PRIMARY> rs.add('10.70.56.196:15552')// 添加新的mongod<br />{ "ok" : 1 }<br /> <br />PRIMARY> rs.status() //<br />{<br /> "set" : "shard2",<br /> "date" : ISODate("2017-11-15T08:54:41Z"),<br /> "myState" : 1,<br /> "members" : [<br /> {<br /> "_id" : 1,<br /> "name" : "10.70.56.201:15552",<br /> "health" : 1,<br /> "state" : 2,<br /> "stateStr" : "SECONDARY",<br /> "uptime" : 42,<br /> "optime" : {<br /> "t" : 1510736078000,<br /> "i" : 1<br /> },<br /> "optimeDate" : ISODate("2017-11-15T08:54:38Z"),<br /> "lastHeartbeat" : ISODate("2017-11-15T08:54:39Z"),<br /> "pingMs" : 0<br /> },<br /> {<br /> "_id" : 2,<br /> "name" : "10.70.56.197:15552",<br /> "health" : 1,<br /> "state" : 1,<br /> "stateStr" : "PRIMARY",<br /> "optime" : {<br /> "t" : 1510736078000,<br /> "i" : 1<br /> },<br /> "optimeDate" : ISODate("2017-11-15T08:54:38Z"),<br /> "self" : true<br /> },<br /> {<br /> "_id" : 3,<br /> "name" : "10.70.56.196:15552",<br /> "health" : 1,<br /> "state" : 2,<br /> "stateStr" : "SECONDARY",<br /> "uptime" : 3,<br /> "optime" : {<br /> "t" : 1510730231000,<br /> "i" : 1<br /> },<br /> "optimeDate" : ISODate("2017-11-15T07:17:11Z"),<br /> "lastHeartbeat" : ISODate("2017-11-15T08:54:40Z"),<br /> "pingMs" : 163<br /> }<br /> ],<br /> "ok" : 1<br />}</p>mongodb 对内存的严重占用以及解决方法【转载】savagertnullhttp://liyanblog.cn/articles/2016/11/10/1478757213733.html2016-11-10T13:53:33+08:00<p><span style="font-size: small;"><br /><br />刚开始使用mongodb的时候,不太注意mongodb的内存使用,但通过查资料发现mongodb对内存的占用是巨大的,在本地测试服务器中,8G的内存居然被占用了45%。汗呀。<br />本文就来剖析一下mongodb对内存的具体使用方法,以及生产环境针对mongodb占大量内存的问题的解决。<br />先看一个MongoDB服务器的top命令结果<br />shell> top -p $(pidof mongod)<br />Mem: 32872124k total, 30065320k used, 2806804k free, 245020k buffers <br />Swap: 2097144k total, 100k used, 2097044k free, 26482048k cached<br /> VIRT RES SHR %MEM<br />1892g 21g 21g 69.6<br /><br />或者 先top后,然后 shift+m 把当前进场按占用内存的多少排序。看看你的mongodb能占用多少内存。<br /><br /><br />先了解一下linux对内存的管理方式:<br />在Linux里(别的系统也差不多),内存有物理内存和虚拟内存之说,物理内存是什么自然无需解释,虚拟内存实际是物理内存的抽象,多数情况下,出于方便性的考虑,程序访问的都是虚拟内存地址,然后操作系统会把它翻译成物理内存地址。<br />很多人会把虚拟内存和Swap混为一谈,实际上Swap只是虚拟内存引申出的一种技术而已:操作系统一旦物理内存不足,为了腾出内存空间存放新内容,就会把当前物理内存中的内容放到交换分区里,稍后用到的时候再取回来,需要注意的是,Swap的使用可能会带来性能问题,偶尔为之无需紧张,糟糕的是物理内存和交换分区频繁的发生数据交换,这被称之为Swap颠簸,一旦发生这种情况,先要明确是什么原因造成的,如果是内存不足就好办了,加内存就可以解决,不过有的时候即使内存充足也可能会出现这种问题,比如MySQL就有可能出现这样的情况,解决方法是限制使用Swap:<br />shell> sysctl -w vm.swappiness=0<br />查看内存情况最常用的是free命令:<br />shell> free -m<br /> total used free shared buffers cached<br />Mem: 32101 29377 2723 0 239 25880<br />-/+ buffers/cache: 3258 28842<br />Swap: 2047 0 2047<br />新手看到used一栏数值偏大,free一栏数值偏小,往往会认为内存要用光了。其实并非如此,之所以这样是因为每当我们操作文件的时候,Linux都会尽可能的把文件缓存到内存里,这样下次访问的时候,就可以直接从内存中取结果,所以cached一栏的数值非常的大,不过不用担心,这部分内存是可回收的,操作系统会按照LRU算法淘汰冷数据。除了cached,还有一个buffers,它和cached类似,也是可回收的,不过它的侧重点在于缓解不同设备的操作速度不一致造成的阻塞,这里就不多做解释了。<br />知道了原理,我们就可以推算出系统可用的内存是free + buffers + cached:<br />shell> echo "2723 + 239 + 25880" | bc -l<br />28842<br />至于系统实际使用的内存是used – buffers – cached:<br />shell> echo "29377 - 239 - 25880" | bc -l<br />3258<br />除了free命令,还可以使用sar命令:<br />shell> sar -r<br />kbmemfree kbmemused %memused kbbuffers kbcached<br /> 3224392 29647732 90.19 246116 26070160<br /> 3116324 29755800 90.52 245992 26157372<br /> 2959520 29912604 91.00 245556 26316396<br /> 2792248 30079876 91.51 245680 26485672<br /> 2718260 30153864 91.73 245684 26563540<br /><br />shell> sar -W<br />pswpin/s pswpout/s<br /> 0.00 0.00<br /> 0.00 0.00<br /> 0.00 0.00<br /> 0.00 0.00<br /> 0.00 0.00<br />希望你没有被%memused吓到,如果不幸言中,请参考free命令的解释。<br /><br />接着咱们分析一下mongodb是怎么使用内存的:<br /><br />目前,MongoDB使用的是内存映射存储引擎,它会把磁盘IO操作转换成内存操作,如果是读操作,内存中的数据起到缓存的作用,如果是写操作,内存还可以把随机的写操作转换成顺序的写操作,总之可以大幅度提升性能。MongoDB并不干涉内存管理工作,而是把这些工作留给操作系统的虚拟缓存管理器去处理,这样的好处是简化了MongoDB的工作,但坏处是你没有方法很方便的控制MongoDB占多大内存,事实上MongoDB会占用所有能用的内存,所以最好不要把别的服务和MongoDB放一起。<br /><br />有时候,即便MongoDB使用的是64位操作系统,也可能会遭遇臭名昭著的OOM问题,出现这种情况,多半是因为限制了虚拟内存的大小所致,可以这样查看当前值:<br /><br />shell> ulimit -a | grep 'virtual' <br />多数操作系统缺省都是把它设置成unlimited的,如果你的操作系统不是,可以这样修改:<br /><br />shell> ulimit -v unlimited<br />不过要注意的是,ulimit的使用是有上下文的,最好放在MongoDB的启动脚本里。<br /><br />有时候,出于某些原因,你可能想释放掉MongoDB占用的内存,不过前面说了,内存管理工作是由虚拟内存管理器控制的,所以通常你只能通过重启服务来释放内存,你一定不齿于这样的方法,幸好可以使用MongoDB内置的closeAllDatabases命令达到目的:<br /><br />mongo> use admin<br />mongo> db.runCommand({closeAllDatabases:1})<br />另外,通过调整内核参数drop_caches也可以释放缓存:<br /><br />shell> sysctl -w vm.drop_caches=1<br />平时可以通过mongo命令行来监控MongoDB的内存使用情况,如下所示:<br /><br />mongo> db.serverStatus().mem:<br />{<br /> "resident" : 22346,<br /> "virtual" : 1938524,<br /> "mapped" : 962283<br />}<br />还可以通过mongostat命令来监控MongoDB的内存使用情况,如下所示:<br />shell> mongostat<br />mapped vsize res faults<br /> 940g 1893g 21.9g 0<br /> 940g 1893g 21.9g 0<br /> 940g 1893g 21.9g 0<br /> 940g 1893g 21.9g 0<br /> 940g 1893g 21.9g 0<br /><br />其中内存相关字段的含义是:<br />mapped:映射到内存的数据大小 <br />visze:占用的虚拟内存大小 <br />res:实际使用的内存大小 <br />注:如果操作不能再内存中完成,结果faults列的数值不会是0,视大小可能有性能问题。<br /><br />在上面的结果中,vsize是mapped的两倍,而mapped等于数据文件的大小,所以说vsize是数据文件的两倍,之所以会这样,是因为本例中,MongoDB开启了journal,需要在内存里多映射一次数据文件,如果关闭journal,则vsize和mapped大致相当。<br /><br />如果想验证这一点,可以在开启或关闭journal后,通过pmap命令来观察文件映射情况:<br />shell> pmap $(pidof mongod)<br />到底MongoDB配备多大内存合适?宽泛点来说,多多益善,如果要确切点来说,这实际取决于你的数据及索引的大小,内存如果能够装下全部数据加索引是最佳情况,不过很多时候,数据都会比内存大,比如本文说涉及的MongoDB实例:<br />mongo> db.stats()<br />{<br /> "dataSize" : 1004862191980,<br /> "indexSize" : 1335929664<br />}<br />本例中索引只有1G多,内存完全能装下,而数据文件则达到了1T,估计很难找到这么大内存,此时保证内存能装下热数据即可,至于热数据有多少,这就是个比例问题了,取决于具体的应用。如此一来内存大小就明确了:内存 > 索引 + 热数据。<br /><br />根据以上的分析我们可以得出几点结论:<br />1. mongodb 直接用操作系统的内存管理器来管理内存。而操作系统采用的是LRU算法淘汰冷数据。<br />2. mongodb可以用重启服务、调整内核参数以及mongodb内部的语法去清理mongodb对内存的缓存。可能存在的问题是:这几种清理方式都是全部清理,这样的话mongodb的内存缓存就失效了。<br />3. mongodb 对内存的使用是可以被监控的,在生产环境中要定时的去监控这些数据。<br />4. mongodb 对内存这种占用方式使其尽量的和其他占用内存的业务分开部署,例如memcahe,sphinx,mysql等。<br />5. 操作系统中的交换分区swap 如果操作频繁的话,会严重降低系统效率。要解决可以禁用交换分区,以及增加内存以及做分布式。<br />6. 生产环境中mongodb所在的主机应该尽量的大内存。<br /></span></p>mongodb java操作 同一个字段的and操作。savagertnullhttp://liyanblog.cn/articles/2015/11/12/1447312686477.html2015-11-12T15:18:06+08:00<p>从网上查了很多 但是没有同一个字段的and的查询。经过研究实现如下 </p>
<p>关系。vc大于1 and pbh大于start AND pbh小于end 按照vc大到小排序,最多显示num条。</p>
<p>DBObject queryCondition = new BasicDBObject();<br /> queryCondition.put("vc", new BasicDBObject("$gt", 1));//大于<br /> <br /> BasicDBObject startendCondition = new BasicDBObject();<br /> if(start!=null){<br /> startendCondition.append("$gt", start);//大于<br /> }<br /> if(end!=null){<br /> startendCondition.append("$lte", end);//小于<br /> }<br /> queryCondition.put("pbh",startendCondition); <br /> <br /> <br /><br /> DBObject sortCondition = new BasicDBObject("vc",-1);<br /> //.limit(10).sort(new BasicDBObject("create_time",-1));<br /> DBCursor resultset = collection.find(queryCondition).sort(sortCondition).limit(num);</p>Maongodb 慢查询Profiling savagertnullhttp://liyanblog.cn/articles/2015/10/09/1444357266357.html2015-10-09T10:21:06+08:00<p style="margin: 8px auto 0px; padding: 0px;">在 MySQL中,慢查询日志是经常作为我们优化数据库的依据,那在MongoDB中是否有类似的功能呢?答案是肯定的,那就是Mongo Database Profiler.不仅有,而且还有一些比MySQL的Slow Query Log更详细的信息。它就是我们这篇文章的主题。</p>
<p style="margin: 8px auto 0px; padding: 0px;"><strong style="margin: 0px auto; padding: 0px;"> 开启 Profiling 功能</strong></p>
<p style="margin: 8px auto 0px; padding: 0px;"> 有两种方式可以控制 Profiling 的开关和级别,第一种是直接在启动参数里直接进行设置。</p>
<p style="margin: 8px auto 0px; padding: 0px;"> 启动MongoDB时加上–profile=级别 即可。</p>
<p style="margin: 8px auto 0px; padding: 0px;"> 也可以在客户端调用db.setProfilingLevel(级别) 命令来实时配置。可以通过db.getProfilingLevel()命令来获取当前的Profile级别。</p>
<table style="margin: 0px auto; table-layout: fixed; border: #cccccc 1px dotted; padding: 0px;" width="95%" border="0" cellspacing="0" cellpadding="6" align="center">
<tbody style="margin: 0px auto; padding: 0px;">
<tr style="margin: 0px auto; padding: 0px;">
<td style="margin: 0px auto; word-wrap: break-word; padding: 0px;" bgcolor="#f3f3f3"> > db.setProfilingLevel(2); <br style="margin: 0px auto; padding: 0px;" /> {"was" : 0 , "ok" : 1} <br style="margin: 0px auto; padding: 0px;" /> > db.getProfilingLevel()</td>
</tr>
</tbody>
</table>
<p style="margin: 8px auto 0px; padding: 0px;"> 上面斜体的级别可以取0,1,2 三个值,他们表示的意义如下:</p>
<p style="margin: 8px auto 0px; padding: 0px;"> 0 – 不开启</p>
<p style="margin: 8px auto 0px; padding: 0px;"> 1 – 记录慢命令 (默认为>100ms)</p>
<p style="margin: 8px auto 0px; padding: 0px;"> 2 – 记录所有命令</p>
<p style="margin: 8px auto 0px; padding: 0px;"> Profile 记录在级别1时会记录慢命令,那么这个慢的定义是什么?上面我们说到其默认为100ms,当然有默认就有设置,其设置方法和级别一样有两种,一种是通过添加–slowms启动参数配置。第二种是调用db.setProfilingLevel时加上第二个参数:</p>
<table style="margin: 0px auto; table-layout: fixed; border: #cccccc 1px dotted; padding: 0px;" width="95%" border="0" cellspacing="0" cellpadding="6" align="center">
<tbody style="margin: 0px auto; padding: 0px;">
<tr style="margin: 0px auto; padding: 0px;">
<td style="margin: 0px auto; word-wrap: break-word; padding: 0px;" bgcolor="#f3f3f3"> db.setProfilingLevel( level , slowms ) <br style="margin: 0px auto; padding: 0px;" /> db.setProfilingLevel( 1 , 10 );</td>
</tr>
</tbody>
</table>
<p style="margin: 8px auto 0px; padding: 0px;"><strong style="margin: 0px auto; padding: 0px;"> 查询 Profiling 记录</strong></p>
<p style="margin: 8px auto 0px; padding: 0px;"> 与MySQL的慢查询日志不同,Mongo Profile 记录是直接存在系统db里的,记录位置 system.profile ,所以,我们只要查询这个Collection的记录就可以获取到我们的 Profile 记录了。</p>
<table style="margin: 0px auto; table-layout: fixed; border: #cccccc 1px dotted; padding: 0px;" width="95%" border="0" cellspacing="0" cellpadding="6" align="center">
<tbody style="margin: 0px auto; padding: 0px;">
<tr style="margin: 0px auto; padding: 0px;">
<td style="margin: 0px auto; word-wrap: break-word; padding: 0px;" bgcolor="#f3f3f3"> > db.system.profile.find() <br style="margin: 0px auto; padding: 0px;" /> {"ts" : "Thu Jan 29 2009 15:19:32 GMT-0500 (EST)" , "info" : "query test.$cmd ntoreturn:1 reslen:66 nscanned:0 <br style="margin: 0px auto; padding: 0px;" /> query: { profile: 2 } nreturned:1 bytes:50" , "millis" : 0} <br style="margin: 0px auto; padding: 0px;" /> db.system.profile.find( { info: /test.foo/ } ) <br style="margin: 0px auto; padding: 0px;" /> {"ts" : "Thu Jan 29 2009 15:19:40 GMT-0500 (EST)" , "info" : "insert test.foo" , "millis" : 0} <br style="margin: 0px auto; padding: 0px;" /> {"ts" : "Thu Jan 29 2009 15:19:42 GMT-0500 (EST)" , "info" : "insert test.foo" , "millis" : 0} <br style="margin: 0px auto; padding: 0px;" /> {"ts" : "Thu Jan 29 2009 15:19:45 GMT-0500 (EST)" , "info" : "query test.foo ntoreturn:0 reslen:102 nscanned:2 <br style="margin: 0px auto; padding: 0px;" /> query: {} nreturned:2 bytes:86" , "millis" : 0} <br style="margin: 0px auto; padding: 0px;" /> {"ts" : "Thu Jan 29 2009 15:21:17 GMT-0500 (EST)" , "info" : "query test.foo ntoreturn:0 reslen:36 nscanned:2 <br style="margin: 0px auto; padding: 0px;" /> query: { $not: { x: 2 } } nreturned:0 bytes:20" , "millis" : 0} <br style="margin: 0px auto; padding: 0px;" /> {"ts" : "Thu Jan 29 2009 15:21:27 GMT-0500 (EST)" , "info" : "query test.foo ntoreturn:0 exception bytes:53" , "millis" : 88}</td>
</tr>
</tbody>
</table>
<p style="margin: 8px auto 0px; padding: 0px;"> 列出执行时间长于某一限度(5ms)的 Profile 记录:</p>
<table style="margin: 0px auto; table-layout: fixed; border: #cccccc 1px dotted; padding: 0px;" width="95%" border="0" cellspacing="0" cellpadding="6" align="center">
<tbody style="margin: 0px auto; padding: 0px;">
<tr style="margin: 0px auto; padding: 0px;">
<td style="margin: 0px auto; word-wrap: break-word; padding: 0px;" bgcolor="#f3f3f3"> > db.system.profile.find( { millis : { $gt : 5 } } ) <br style="margin: 0px auto; padding: 0px;" /> {"ts" : "Thu Jan 29 2009 15:21:27 GMT-0500 (EST)" , "info" : "query test.foo ntoreturn:0 exception bytes:53" , "millis" : 88}</td>
</tr>
</tbody>
</table>
<p style="margin: 8px auto 0px; padding: 0px;"> 查看最新的 Profile 记录:</p>
<p style="margin: 8px auto 0px; padding: 0px;"> db.system.profile.find().sort({$natural:-1})</p>
<p style="margin: 8px auto 0px; padding: 0px;"> Mongo Shell 还提供了一个比较简洁的命令show profile,可列出最近5条执行时间超过1ms的 Profile 记录。</p>
<p style="margin: 8px auto 0px; padding: 0px;"><strong style="margin: 0px auto; padding: 0px;"> Profile 信息内容详解:</strong></p>
<p style="margin: 8px auto 0px; padding: 0px;"> ts-该命令在何时执行.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> millis Time-该命令执行耗时,以毫秒记.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> info-本命令的详细信息.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> query-表明这是一个query查询操作.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> ntoreturn-本次查询客户端要求返回的记录数.比如, findOne()命令执行时 ntoreturn 为 1.有limit(n) 条件时ntoreturn为n.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> query-具体的查询条件(如x>3).</p>
<p style="margin: 8px auto 0px; padding: 0px;"> nscanned-本次查询扫描的记录数.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> reslen-返回结果集的大小.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> nreturned-本次查询实际返回的结果集.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> update-表明这是一个update更新操作.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> fastmod-Indicates a fast modify operation. See Updates. These operations are normally quite fast.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> fastmodinsert – indicates a fast modify operation that performed an upsert.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> upsert-表明update的upsert参数为true.此参数的功能是如果update的记录不存在,则用update的条件insert一条记录.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> moved-表明本次update是否移动了硬盘上的数据,如果新记录比原记录短,通常不会移动当前记录,如果新记录比原记录长,那么可能会移动记录到其它位置,这时候会导致相关索引的更新.磁盘操作更多,加上索引更新,会使得这样的操作比较慢.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> insert-这是一个insert插入操作.</p>
<p style="margin: 8px auto 0px; padding: 0px;"> getmore-这是一个getmore 操作,getmore通常发生在结果集比较大的查询时,第一个query返回了部分结果,后续的结果是通过getmore来获取的。</p>
<p style="margin: 8px auto 0px; padding: 0px;"><strong style="margin: 0px auto; padding: 0px;"> MongoDB 查询优化</strong></p>
<p style="margin: 8px auto 0px; padding: 0px;"> 如果nscanned(扫描的记录数)远大于nreturned(返回结果的记录数)的话,那么我们就要考虑通过加索引来优化记录定位了。</p>
<p style="margin: 8px auto 0px; padding: 0px;"> reslen 如果过大,那么说明我们返回的结果集太大了,这时请查看find函数的第二个参数是否只写上了你需要的属性名。(类似 于MySQL中不要总是select *)</p>
<p style="margin: 8px auto 0px; padding: 0px;"> 对于创建索引的建议是:如果很少读,那么尽量不要添加索引,因为索引越多,写操作会越慢。如果读量很大,那么创建索引还是比较划算的。(和RDBMS一样,貌似是废话 -_-!!)</p>
<p style="margin: 8px auto 0px; padding: 0px;"><strong style="margin: 0px auto; padding: 0px;"> MongoDB 更新优化</strong></p>
<p style="margin: 8px auto 0px; padding: 0px;"> 如果写查询量或者update量过大的话,多加索引是会有好处的。以及~~~~(省略N字,和RDBMS差不多的道理)</p>
<p style="margin: 8px auto 0px; padding: 0px;"> Use fast modify operations when possible (and usually with these, an index). See Updates.</p>
<p style="margin: 8px auto 0px; padding: 0px;"><strong style="margin: 0px auto; padding: 0px;"> Profiler 的效率</strong></p>
<p style="margin: 8px auto 0px; padding: 0px;"> Profiling 功能肯定是会影响效率的,但是不太严重,原因是他使用的是system.profile 来记录,而system.profile 是一个capped collection 这种collection 在操作上有一些限制和特点,但是效率更高。</p>mongodb 避免Out of semaphores to get db connection errorsavagertnullhttp://liyanblog.cn/articles/2014/07/24/1406195047737.html2014-07-24T17:44:07+08:00<div class="bct fc05 fc11 nbw-blog ztag"><span style="color: #ff0000; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; line-height: 25px; text-align: -webkit-auto;">com.mongodb.DBPortPool$SemaphoresOut: Out of semaphores to get db</span>
<div><span style="color: #ff0000; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; line-height: 25px; text-align: -webkit-auto;"> </span></div>
<div><span style="color: #ff0000; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; line-height: 25px; text-align: -webkit-auto;"> </span></div>
<div>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;">MongoDB 并发测试,报出上述错误。究其原因,是数据库连接数太少,资源耗尽。查看com.mongodb.MongoOptions源代码,其中有 connectionsPerHost和threadsAllowedToBlockForConnectionMultiplier两个重要的属性。</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> connectionsPerHost:每个主机的连接数</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> threadsAllowedToBlockForConnectionMultiplier:线程队列数,它以上面connectionsPerHost值相乘的结果就是线程队列最大值。如果连接线程排满了队列就会抛出“<span style="line-height: 25px; color: #ff0000;">Out of semaphores to get db</span>”错误。</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> connectionsPerHost默认是10,threadsAllowedToBlockForConnectionMultiplier默认是5,也就是线程池有50个连接数可供使用。因此只要将这个属性的值加大就可以避免上述错误。</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> </p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> 其它属性设置:</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> maxWaitTime:最大等待连接的线程阻塞时间</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> connectTimeout:连接超时的毫秒。0是默认和无限</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> socketTimeout:socket超时。0是默认和无限</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> autoConnectRetry:这个控制是否在一个连接时,系统会自动重试</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;"> </p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;">java设置方法:</p>
<p style="line-height: 25px; color: #333333; font-family: Verdana, Arial, Helvetica, 宋体, sans-serif; text-align: -webkit-auto;">MongoOptions options = new MongoOptions();<br /> options.connectionsPerHost = 100;//链接池数量 默认10 。避免Out of semaphores to get db connection error<br /> options.autoConnectRetry = true;<br /> options.threadsAllowedToBlockForConnectionMultiplier=5;<br /> options.slaveOk = true;<br /> mongo = new Mongo(replicaSetSeeds, options);</p>
</div>
</div>mongodb 数据文件里的moveChunk是什么。可以删除savagertnullhttp://liyanblog.cn/articles/2014/05/20/1400573704766.html2014-05-20T16:15:04+08:00<p><strong> 我可以把moveChunk目录里的旧文件删除吗?</strong></p>
<p>没问题,这些文件是在分片(shard)进行均衡操作(balancing)的时候产生的临时文件。一旦这些操作已经完成,相关的临时文件也应该被删除掉。但目前清理工作是需要手动的,所以请小心地考虑再释放这些文件的空间。</p>MongoDB NoSQL数据库的面试问答吧savagertnullhttp://liyanblog.cn/articles/2014/05/20/1400573628224.html2014-05-20T16:14:12+08:00<p>MongoDB NoSQL数据库的面试问答吧:</p>
<p><strong>1. 你说的NoSQL数据库是什么意思?NoSQL与RDBMS直接有什么区别?为什么要使用和不使用NoSQL数据库?说一说NoSQL数据库的几个优点?</strong></p>
<p>我写了一篇完整的博客来回答这些问题,看<a href="http://theprofessionalspoint.blogspot.in/2014/01/nosql-vs-rdbms-why-and-why-not-to-use.html" target="_blank"><span style="color: #337fe5;">这里</span></a></p>
<p><strong>2. NoSQL数据库有哪些类型?</strong></p>
<p><a href="http://theprofessionalspoint.blogspot.in/2014/01/types-and-examples-of-nosql-databases.html" target="_blank"><span style="color: #337fe5;">NoSQL数据库的类型</span></a></p>
<p>例如:MongoDB, Cassandra, CouchDB, Hypertable, Redis, Riak, Neo4j, HBASE, Couchbase, MemcacheDB, RevenDB and Voldemort are the examples of NoSQL databases. <a href="http://theprofessionalspoint.blogspot.in/2014/01/12-best-free-and-open-source-nosql.html" target="_blank"><span style="color: #337fe5;">详细阅读</span></a>。</p>
<p><strong>3. MySQL与MongoDB之间最基本的差别是什么?</strong></p>
<p>MySQL和MongoDB两者都是免费开源的数据库。MySQL和MongoDB有许多基本差别包括数据的表示(data representation),查询,关系,事务,schema的设计和定义,标准化(normalization),速度和性能。通过比较MySQL 和MongoDB,实际上我们是在比较关系型和非关系型数据库。<a href="http://theprofessionalspoint.blogspot.in/2013/12/mysql-vs-mongodb-basic-differences.html" target="_blank"><span style="color: #337fe5;">详细阅读</span></a></p>
<p><strong>4. 你怎么比较MongoDB、CouchDB及CouchBase?</strong></p>
<p>MongoDB和CouchDB都是面向文档的数据库。MongoDB和CouchDB都是开源NoSQL数据库的最典型代表。 除了都以文档形式存储外它们没有其他的共同点。MongoDB和CouchDB在数据模型实现、接口、对象存储以及复制方法等方面有很多不同。</p>
<p>细节可以参见下面的链接:</p>
<p><a href="http://theprofessionalspoint.blogspot.in/2014/01/couchdb-vs-couchbase-differences-and.html" target="_blank"><span style="color: #337fe5;">MongDB vs CouchDB</span></a></p>
<p><a href="http://theprofessionalspoint.blogspot.in/2014/01/couchdb-vs-couchbase-differences-and.html" target="_blank"><span style="color: #337fe5;">CouchDB vs CouchBase</span></a></p>
<p><strong>5. MongoDB成为最好NoSQL数据库的原因是什么?</strong></p>
<p>以下特点使得MongoDB成为最好的NoSQL数据库:</p>
<p> </p>
<ul>
<li><span style="line-height: 1.5;">面向文件的</span></li>
<li><span style="line-height: 1.5;">高性能</span></li>
<li><span style="line-height: 1.5;">高可用性</span></li>
<li><span style="line-height: 1.5;">易扩展性</span></li>
<li><span style="line-height: 1.5;">丰富的查询语言</span></li>
</ul>
<p><strong>6.32位系统上有什么细微差别?</strong></p>
<p>journaling会激活额外的内存映射文件。这将进一步抑制32位版本上的数据库大小。因此,现在journaling在32位系统上默认是禁用的。</p>
<p><strong>7. journal回放在条目(entry)不完整时(比如恰巧有一个中途故障了)会遇到问题吗?</strong></p>
<p>每个journal (group)的写操作都是一致的,除非它是完整的否则在恢复过程中它不会回放。</p>
<p><strong>8. 分析器在MongoDB中的作用是什么?</strong></p>
<p>MongoDB中包括了一个可以显示数据库中每个操作性能特点的数据库分析器。通过这个分析器你可以找到比预期慢的查询(或写操作);利用这一信息,比如,可以确定是否需要添加索引。</p>
<p><strong>9. 名字空间(namespace)是什么?</strong></p>
<p>MongoDB存储BSON对象在丛集(collection)中。数据库名字和丛集名字以句点连结起来叫做名字空间(namespace)。</p>
<p><strong>10. 如果用户移除对象的属性,该属性是否从存储层中删除?</strong></p>
<p>是的,用户移除属性然后对象会重新保存(re-save())。</p>
<p><strong>11. 能否使用日志特征进行安全备份?</strong></p>
<p>是的。</p>
<p><strong>12. 允许空值null吗?</strong></p>
<p>对于对象成员而言,是的。然而用户不能够添加空值(null)到数据库丛集(collection)因为空值不是对象。然而用户能够添加空对象{}。</p>
<p><strong>13. 更新操作立刻fsync到磁盘?</strong></p>
<p>不会,磁盘写操作默认是延迟执行的。写操作可能在两三秒(默认在60秒内)后到达磁盘。例如,如果一秒内数据库收到一千个对一个对象递增的操作,仅刷新磁 盘一次。(注意,尽管fsync选项在命令行和经过getLastError_old是有效的)(译者:也许是坑人的面试题??)。</p>
<p><strong>14. 如何执行事务/加锁?</strong></p>
<p>MongoDB没有使用传统的锁或者复杂的带回滚的事务,因为它设计的宗旨是轻量,快速以及可预计的高性能。可以把它类比成MySQL MylSAM的自动提交模式。通过精简对事务的支持,性能得到了提升,特别是在一个可能会穿过多个服务器的系统里。</p>
<p><strong>15. 为什么我的数据文件如此庞大?</strong></p>
<p>MongoDB会积极的预分配预留空间来防止文件系统碎片。</p>
<p><strong>16. 启用备份故障恢复需要多久?</strong></p>
<p>从备份数据库声明主数据库宕机到选出一个备份数据库作为新的主数据库将花费10到30秒时间。这期间在主数据库上的操作将会失败--包括写入和强一致性读 取(strong consistent read)操作。然而,你还能在第二数据库上执行最终一致性查询(eventually consistent query)(在slaveOk模式下),即使在这段时间里。</p>
<p><strong>17. 什么是master或primary?</strong></p>
<p>它是当前备份集群(replica set)中负责处理所有写入操作的主要节点/成员。在一个备份集群中,当失效备援(failover)事件发生时,一个另外的成员会变成primary。</p>
<p><strong>18. 什么是secondary或slave?</strong></p>
<p>Seconday从当前的primary上复制相应的操作。它是通过跟踪复制oplog(local.oplog.rs)做到的。</p>
<p><strong>19. 我必须调用getLastError来确保写操作生效了么?</strong></p>
<p>不用。不管你有没有调用getLastError(又叫"Safe Mode")服务器做的操作都一样。调用getLastError只是为了确认写操作成功提交了。当然,你经常想得到确认,但是写操作的安全性和是否生效不是由这个决定的。</p>
<p><strong>20. </strong><strong>我应该启动一个集群分片(sharded)还是一个非集群分片的 MongoDB 环境?</strong></p>
<p>为开发便捷起见,我们建议以非集群分片(unsharded)方式开始一个 MongoDB 环境,除非一台服务器不足以存放你的初始数据集。从非集群分片升级到集群分片(sharding)是无缝的,所以在你的数据集还不是很大的时候没必要考虑 集群分片(sharding)。</p>
<p><strong>21. 分片(sharding)和复制(replication)是怎样工作的?</strong></p>
<p>每一个分片(shard)是一个分区数据的逻辑集合。分片可能由单一服务器或者集群组成,我们推荐为每一个分片(shard)使用集群。</p>
<p><strong>22. 数据在什么时候才会扩展到多个分片(shard)里?</strong></p>
<p>MongoDB 分片是基于区域(range)的。所以一个集合(collection)中的所有的对象都被存放到一个块(chunk)中。只有当存在多余一个块的时候, 才会有多个分片获取数据的选项。现在,每个默认块的大小是 64Mb,所以你需要至少 64 Mb 空间才可以实施一个迁移。</p>
<p><strong>23. 当我试图更新一个正在被迁移的块(chunk)上的文档时会发生什么?</strong></p>
<p>更新操作会立即发生在旧的分片(shard)上,然后更改才会在所有权转移(ownership transfers)前复制到新的分片上。</p>
<p>24. 如果在一个分片(shard)停止或者很慢的时候,我发起一个查询会怎样?</p>
<p>如果一个分片(shard)停止了,除非查询设置了“Partial”选项,否则查询会返回一个错误。如果一个分片(shard)响应很慢,MongoDB则会等待它的响应。</p>
<p><strong>25. 我可以把moveChunk目录里的旧文件删除吗?</strong></p>
<p>没问题,这些文件是在分片(shard)进行均衡操作(balancing)的时候产生的临时文件。一旦这些操作已经完成,相关的临时文件也应该被删除掉。但目前清理工作是需要手动的,所以请小心地考虑再释放这些文件的空间。</p>
<p><strong>26. 我怎么查看 Mongo 正在使用的链接?</strong></p>
<p>db._adminCommand("connPoolStats");</p>
<p><strong>27. 如果块移动操作(moveChunk)失败了,我需要手动清除部分转移的文档吗?</strong></p>
<p>不需要,移动操作是一致(consistent)并且是确定性的(deterministic);一次失败后,移动操作会不断重试;当完成后,数据只会出现在新的分片里(shard)。</p>
<p><strong>28. 如果我在使用复制技术(replication),可以一部分使用日志(journaling)而其他部分则不使用吗?</strong></p>
<p>可以。</p>mongodb拷贝数据库copyDatabase()。实现释放磁盘空间的方法。savagertnullhttp://liyanblog.cn/articles/2013/09/07/1378520866654.html2013-09-07T10:27:46+08:00<p>db.copyDatabase("from","to","127.0.0.1:16161");</p>
<p>将127.0.0.1上的from库。拷贝到to库。</p>
<p>这样做有一个额外的好处。就是from库中可能是删除过数据的库。看我们知道删除数据时磁盘空间是不会被释放的。参考博客里的另一篇文章:<a href="http://liyanblog.cn/articles/2013/08/31/1377941853853.html" target="_blank"><span style="font-size: small;">mongodb删除集合后磁盘空间不释放</span></a></p>
<p>肯能造成占用很大磁盘空间。虽然可以用 db.repairDatabase()修复数据。但这种方法有两个不好的地方。1.在生产上操作如果意外停止可能会造成数据无法恢复的危险。2.如果磁盘空间不足,小于现在这个db时间占有的空间,这种情况是用不了 db.repairDatabase()的。</p>
<p>所以介绍用db.copyDatabase可以备份复制数据的方法。</p>
<p>1.db.copyDatabase("from","to","127.0.0.1:16161");复制出一个新的to数据库。这个已经是最小数据占用的数据。会在数据目录下产生to的相关数据文件。</p>
<p>2.将所有程序的配置从from库改为to库。测试无误。</p>
<p>3.这时可以删除from库。方法。use from 后 db.dropDatabase()。这个方法的好处是可以时间将磁盘上的数据删除掉。节省出很大的空间。</p>
<p>磁盘紧张的同学可以参考以上方法。</p>转:基于MongoDB GridFS的图片存储savagertnullhttp://liyanblog.cn/articles/2013/09/03/1378201781024.html2013-09-03T17:50:27+08:00<p>商品图片,平均200-500K,说大不大,说小不小,但量大且细碎,最早通过页面上传,全部保存在文件里,且不分目录,管理和索引都很慢,几乎无法备份,读取也很慢。</p>
<p>改进方案由大鱼设计,图片是保存在MySQL表里,每10万张图就换一张新表,操作语言是PHP,它解决了图片备份和缓存的问题。</p>
<p>经过一段运行时间后,我对效果并不满意,主要是速度还是有些慢,尤其是第一次加载的过程。这期间又负责主体商品数据迁移到MongoDB,大致研究了一下GridFS,并做了些测试,感觉这个比MySQL要靠谱,且MongoDB还有Sharding和Replica Set支持,帮我解决了分布存储的问题,很是诱人,决定一试。</p>
<p>设计思路和需求整理:</p>
<p>决不允许重复图片存在 <br />文件只有原始的需要保留,其他各尺寸和效果都可以由原图生成 <br />图片URL总是固定的,不管它出现在哪里 <br />缩略图生成规则也简单的体现在URL里,参考 Abusing Amazon images http://aaugh.com/imageabuse.html<br />第一次请求,由图片处理程序生成静态文件,以后请求即直接定位到静态文件 <br />多年前,郝培强同学送过我一本《Python语言入门》,但这么些年里只写过三两个小工具,按熟悉程度依然算新手。既然这个解决方案撞枪口上了,于是有改用Python实现的念头。我是这么想的,1.要简单;2.要快,不光运行快,还要写得快;3.最好是常驻型程序。貌似只有Python和Ruby符合,但Ruby我不熟悉,那就用Python好了。某个周六,花了一天时间,写了个雏形,支持图片读取并显示。又花了N天,添加管理和上传。</p>
<p>上传到github,命名为ImSto,将它作为我的第一个开源项目。</p>
<p>关于Python的Web框架,不得不絮叨几句,那真叫一个多,看了一些评论,也粗略研究了Pylons和CherryPy,很久以前学过一点点Django。但感觉似乎都有些复杂,这个需求也不复杂,决定干脆不用任何框架,自己动手丰衣足食算了。</p>
<p>所用到的组件:</p>
<p>MongoDB (GridFS): 这个不用说了,核心存储,初期环境用到了三台主机组成的 Replica Sets <br />Nginx: 解析URL并定位到静态文件,如果未生成则转向uWSGI程序去生成图片 <br />Python + pymongo <br />ImageMagick: 用来生成图片缩略图,有两种调用方式:Api和命令行shell。Demo环境由于内存使用限制,用了shell方式。 <br />uWSGI: 是用纯C写的WSGI服务器,支持多种语言(主要是Python)和Web Server(官方首推Cherokee和Nginx)。有点儿类似PHP-FPM。 <br />项目地址: https://github.com/liut/imsto 只是完成了 TODO里的部分核心功能,代码结构也比较粗糙,待逐步重构。</p>
<p>演示地址: http://demo.imsto.org:81/ 稍后添加权限认证,所以,在这之前请随便添随便删,不要客气。</p>
<p>Update:<br />1. 上传的页面使用了 html5的一些特性,为了实现Ajax上传和进度显示,以及即时预览,暂时只支持Firefox3.5+。稍后再改进。<br />2. 请不要向我推荐用 Flash,谢谢。</p>
<p> </p>mongodb删除集合后磁盘空间不释放 savagertnullhttp://liyanblog.cn/articles/2013/08/31/1377941853853.html2013-08-31T17:37:33+08:00<p>mongodb删除集合后磁盘空间不释放,只有用db.repairDatabase()去修复才能释放。</p>
<p>修复可能要花费很长的时间,在使用db.repairDatabase()去修复时一定要停掉读写,并且mongodb要有备机才可以,不然千万不要随便使用db.repairDatabase()来修复数据库,切记。</p>
<p> </p>
<p>但是在修复的过程中如果出现了非正常的mongodb的挂掉,再次启动时启动不了的,需要先修复才可以,可以利用./mongod --repair --dbpath=/data/mongo/ 如果你是把数据库单独的放在一个文件夹中指定dbpath时就指向要修复的数据库就可以</p>