55最佳实践系列:MongoDB最佳实践

标签: 最佳实践 系列 mongodb | 发表时间:2012-12-15 15:48 | 作者:旁观者
出处:http://www.cnblogs.com/zhengyun_ustc/
@郑昀汇总 创建日期:2012/9
 
Application Design:
1) 如果发现query没使用你预期的索引,请用hint强制使用指定索引
主站商品中心所使用的文档字段很多,各种索引建得也不少。在沙创排查慢查询时,曾百思不得其解,为什么明明建的有联合索引,查询起来还是非常慢呢,直到显式指定使用该联合索引。
hint的例子:
    db.collection.find({"age" : 18, "username" : /.*/}).hint({"username" : 1, "age" : 1})
 
2) Design documents to be self-sufficient, 设计 自给自足的文档
MongoDB 应该是一个大的、无声的数据存储(big, dumb data store)。它几乎不需做任何处理,只是负责存储和读取数据。你应该坚持这个目的,避免强迫 MongoDB 做一些客户端可以进行的计算工作。
如果真的想算一些文档里没有显式存储的数据,你有两个选择:
——招致严重的性能惩罚(让 MongoDB 用JavaScript 做运算);
——在文档中显式存储这些数据。
 
Implementation:
3) Override _id when you have your own simple, unique id
如果你的文档自己有明确的唯一键值,不需要 ObjectId 属性,那么请覆盖默认的 _id 字段,反正你也要在自己的 unique id 上建唯一索引。
 
Optimization:
4)数据量很大时,建联合索引时,不妨对比下索引升序和降序的查询效率
db.collection.ensureIndex({"store_id":- 1, "shop_id": 1})
上面的1代表ascending升序,-1代表descending降序。
单个字段建索引时,不需要考虑索引升序还是降序,都行。
但联合索引下的排序或范围查询(包括$in, $gt, $lt 等),需要重视索引设为升序还是降序。孙国玺认为,最好用大数据模拟一下业务场景,商户中心曾发现设-1比1快10倍以上。
 
5)如需在联合索引下排序,索引的建立方法
MongoDB 和 MySQL 都是B-Tree结构索引,所以一般来说,联合索引都可以这么建:
查询语句是:
    db.collection.find({x : 1,y : 2}).sort({z : 1})
那么,索引可以是:
    db.collection.ensureIndex({x : 1, y : 1,z : 1})//即x+y+z
也可以是:
    db.collection.ensureIndex({y : 1, x : 1,z : 1})//即y+x+z
排序字段总在联合索引的最后。
尽量把能过滤数据量多的字段放在前面。
但如果涉及范围查询(Range Queries),就要小心了。
查询语句是:
    db.collection.find({"country": {"$in": ["ZH", "EN"]}}).sort({"cars": 1})
那么较好的索引是:
    db.collection.ensureIndex({"cars": 1,"country": 1})
即,在范围查询(包括$in, $gt, $lt 等)时,其实刻意在后面追加排序索引通常是没有效果的。因为在进行范围查询的过程中,我们得到的结果集本身并不是按追加的这个字段来排的,还需要进行一次额外的排序才行。而在这种情况下,可能反序建立索引(排序字段在前、范围查询字段在后)反而会是一个比较优的选择。当然,是否更优也和具体的数据集有关,还是要实测。
再举一个例子:
查询语句是:
    db.collection.find({x : 1,y : {$in:[1,2]}}).sort({z : 1})
那么较好的索引是:
    db.collection.ensureIndex({x : 1, z : 1,y : 1})//即x+z+y
 
6)养成用 explain 确认是否充分利用了索引的 习惯
请确认你的查询是否充分利用到了索引,用explain命令查看一下查询执行的情况,添加必要的索引,避免扫表操作。
 
7)查询尽量采用分页,并且尽快释放游标
 
8) 避免使用不会命中索引的语法,如 $nin
 
Data Safety and Consistency:

9)总是使用 Replica Sets (复制群集,副本集):

背景: Replica Sets 通过自动 failover 机制提供MongoDB的高可用性。Replica sets are a form of asynchronous  master/slave replication, adding automatic failover and automatic recovery of member nodes
应用点:在应用中,如 primary 机器出现故障,那么某一台 secondary 机器就会通 过选举成为新的 primary ,整个集群仍然能够提供正常服务。我们的服务不会支持无同步机制的 MongoDB 部署方案。
图例:
http://images.cnblogs.com/cnblogs_com/zhengyun_ustc/255879/o_clipboard%20-011%20%E5%89%AF%E6%9C%AC.png
另,使用 Replica Sets 时,最好加1台仲裁服务器。
 
 
10) 默认开启 journaling 日志:
背景:64-bitMongoDB 1.9.2+以上默认开启  Journaling 功能。32-bit或1.9.2以下版本,则需在命令行启动时加上 --journal 。
Journaling 的出现归因于某用户在单机使用 MongoDB 时执行了 kill -9 操作,导致数据不可用后提出的。
开启该功能时,变更会先写入 Journaling 日志,​定期集中提交​,然后在真实数据上进行这些变更。如果服务器安全关闭,日志会被清除。在服务器启动时,如果存在 Journaling 日志​,则会进行回放。这保证了那些已写入、但在服务器崩溃前还没有回放的​日志能在用户连接前​被执行。​ 
应用点: 郑昀强烈建议你在部署时开启 Journaling 日志。注意数据文件的存放位置。在使用时,请确认你的数据文件处于一个持久化存储中(比如/data /mongodb目录)。也可以使用非持久化的设备进行数据文件存储,不过你最好小心再小心,因为这可能会对你的集群架构造成影响。
热数据最好能放在内存中。能够保持热数据(以及索引数据)一直放在内存中,这一点非常重要,它将对整个集群的性能造成影响。如果通过监控发现 page fault 的数量增加,那么很可能就是热数据量超出了可用内存大小。当热数据量超出了可用内存量时,通常有两种解决方法:增加内存和数据分片。建议先增加内存,再考虑通过数据分片的方式解决。
 
Administration:
11) 保持版本更新:
应用点:保持版本更新很重要,10gen 在每个版本中都会修复一些问题,使 MongoDB 的运行更出色。比如在 2.0.x版本中,MongoDB 的存储性能和并发性能就有极大提高,同时还包括索引优化、Bug修复以及 compaction 命令等一系列改进。
 
12) 不要在32位系统上使用MongoDB:
背景:在32位机器上,MongoDB只能存储约2.5GB的数据。因为 MongoDB在内部实现上是通过内存映射的方式来提高性能的,所以在32位机器上其内存地址本身就限制了数据容量。
 
13) 压力过大升级服务器配置:
应用点:如果机器负载达到65%,那么应该考虑升级机器配置。在日常使用中,最好保持负载低于65%。同时这也对数据恢复和纵向扩展有影响。
 
14) 确定热数据大小:
使用MongoDB,你最好保证你的热数据在你机器的内存大小之下,保证内存能容纳所有热数据。
 
15) 选择正确的文件系统:
MongoDB 的数据文件是采用的预分配模式,并且在 Replication 里面,Master 和 Replica Sets 的非 Arbiter 节点都是会预先创建足够的空文件用以存储操作日志。
这些文件分配操作在一些文件系统上可能会非常慢,导致进程被 Block 。所以我们应该选择那些空间分配快速的文件系统。这里的结论是尽量不要用ext3,用ext4或者xfs。
 
16) 选用合适的raid和磁盘:
尽量使用raid10,避免使用raid5,经济条件允许的情况下最好使用ssd硬盘。
 
17)如何 关闭 MongoDB:
MongoDB 数据库在关闭的时候使用 kill -2 <mongo-pid>,
或者在 mongo 终端中使用  
use admin
db.shutdownServer()
 
18) 分片( sharding) 需谨慎:
应用点:分片策略会受数据访问特点的影响,所以在进行数据分片前,最好先理清楚数据的访问模式,并想明白是否确实需要分片。
由于 Shard Key 对性能的影响非常大,所以 选择一个好的 Sharding Key 是非常重要的。对于 Shard Key 的选定直接决定了集群中数据分布是否均衡、集群性能是否合理。选择 Shard Key 的一个非常重要因素是万一某一个分片彻底不可访问了,受到影响的Chunk有多大(即使是用 Replica Set)。
Config Server 对整个集群的健康运行是至关重要的,所以一旦你选择使用 分片机制,就一定要保证生产环境里有3个 Config Servers 。
永远不要删除 Config Servers 的数据,要确保频繁地对这些数据进行日常备份。如果可能,通过域名来指定节 点的地址,比如在/etc/hosts文件中指定相应的本地域名,这能让你在集群配置上更灵活。Config Servers 的压力很小,但还是必须运行在 64-bit instances 上。
千万不要把3个 Config Servers 都放在同一个 instance 上!
 
 
参考资源:
3)部分内容来自宋涛,刘奎波和孙国玺

赠图几枚:
 

本文链接

相关 [最佳实践 系列 mongodb] 推荐:

55最佳实践系列:MongoDB最佳实践

- - 博客园_旁观者
@郑昀汇总 创建日期:2012/9. 1) 如果发现query没使用你预期的索引,请用hint强制使用指定索引. 主站商品中心所使用的文档字段很多,各种索引建得也不少. 在沙创排查慢查询时,曾百思不得其解,为什么明明建的有联合索引,查询起来还是非常慢呢,直到显式指定使用该联合索引. 2) Design documents to be self-sufficient, 设计 自给自足的文档.

MongoDB最佳实践

- - NoSQLFan
将 MongoDB加入到我们的服务支持列表中,是整个团队年初工作计划中的首要任务. 但我们感觉如果先添加一项对NoSQL存储的支持,而不是先升级已支持的关系型数据库,可能对用户不太好,毕竟目前的用户都使用关系型数据库. 所以我们决定将引入MongoDB这项工作放到升级MySQL和PostgreSQL之后来做.

55最佳实践系列:Logging最佳实践

- - 博客园_旁观者
@郑昀汇总 创建日期:2012/10. ASAP (As Soon As Possible)原则. 当你意识到靠现有的日志无法定位问题时,. 当现象难以在你的开发环境重现时,. 请不要执著于枯坐肉眼看代码,因为:一)不一定是你代码逻辑问题,可能是脏数据造成的,是老业务数据造成的,是分布式环境造成的,是其他子系统造成的;二)线上业务处于不稳定中,条件不允许问题定位无限期.

最佳实践系列:前端代码标准和最佳实践

- - 博客园_旁观者
最佳实践系列:前端代码标准. @窝窝商城前端(刘轶/李晨/徐利/穆尚)翻译于2012年 版本0.55 @郑昀校对. isobar的这个前端代码标准和最佳实践文档,涵盖了Web应用开发的方方面面,我们翻译了大部分章节,并做了注解. 渐进增强; Combo Handler; Quirks Mode; 浏览器盒子模型; 选择器特殊性; Spacer Image; CSS Sprites; PNG8;.

jQuery最佳实践

- andi - 阮一峰的网络日志
上周,我整理了《jQuery设计思想》. 那篇文章是一篇入门教程,从设计思想的角度,讲解"怎么使用jQuery". 今天的文章则是更进一步,讲解"如何用好jQuery". 我主要参考了Addy Osmani的PPT《提高jQuery性能的诀窍》(jQuery Proven Performance Tips And Tricks).

PHP最佳实践

- xiangqian - 阮一峰的网络日志
虽然名字叫《PHP最佳实践》,但是它主要谈的不是编程规则,而是PHP应用程序的合理架构. 它提供了一种逻辑和数据分离的架构模式,属于MVC模式的一种实践. 我觉得,这是很有参考价值的学习资料,类似的文章网上并不多,所以一边学习,一边就把它翻译了出来. 根据自己的理解,我总结了它的MVC模式的实现方式(详细解释见译文):.

[mongodb] java操作mongodb

- - 数据库 - ITeye博客
           //实例化Mongo对象,连接27017端口.                               //连接名为yourdb的数据库,假如数据库不存在的话,mongodb会自动建立. //从Mongodb中获得名为yourColleection的数据集合,如果该数据集合不存在,Mongodb会为其新建立.

文章: Grails最佳实践

- - InfoQ cn
我在IntelliGrape工作,这是一家专门使用Groovy & Grails进行开发的公司. 本文是我们Grails项目遵循的最佳实践的基本清单,收集自邮件列表、Stack Overflow、博文, 播客和 IntelliGrape的内部讨论. 它们分为控制器、服务、Domain、视图、TagLib、测试和其他.

PHP最佳实践(译)

- - CSDN博客Web前端推荐文章
原文:  PHP Best Practices-A short, practical guide for common and confusing PHP tasks. 译者: youngsterxyf. 本文档最后审阅于2013年3月8日. 由我, Alex Cabal,维护该文档. 我编写PHP程序已有很长一段时间了,当前我 经营着 Scribophile,由认真作家组成的一个在线写作团体,  Writerfolio,为自由职业者提供的一个易用写作工具集,以及  Standard Ebooks,一个图文并茂、无数字版权管理的公共领域电子书出版商.

Log4j最佳实践(原) - Mainz

- - 博客园_Mainz's Blog
本文是结合项目中使用 Log4j总结的最佳实践,非转载. 网上可以找到的是这一篇《 Log4j最佳实践》. 本来 Log4j使用是非常简单的,无需多介绍其用法,这只是在小型项目中;但在 大型的项目中使用 log4j不太一样. 大型项目非常依赖日志,因为解决线上问题必须依靠log,依靠大量的日志.