MongoDB容量规划

标签: MongoDB 内存 容量规划 硬盘 | 发表时间:2011-10-26 21:01 | 作者:nosqlfan gOODiDEA
出处:http://blog.nosqlfan.com

上周在公司做了一个NoSQL和MongoDB相关的技术分享,会后有同事问及MongoDB对内存需求的问题,做了简单回复。今天就写篇文章对MongoDB容量规划做一个比较详细的总结。若有不对之处还望各位指正。

存储是什么?

首先我们要问一个很傻的问题:存储是什么。存储就是用来装数据的东西,它需要满足以下两点基本需求:

  • 1.存储数据
  • 2.读取数据

基于这两点,我们需要问的问题就是,这个存储能够存多少数据,能够提供多高的写入速度,能够提供多高的读取速度。而这些参数,通常是受存储所在的机器配置所影响。

我们在做性能测试时,通常会达到系统某个环节的最大值。也就是我们说的系统瓶颈,是CPU先跑满了,还是磁盘IO跟不上,或者是网卡带宽跑满了,这些是我们做性能测试时需要得到的结果。以及哪些瓶颈能够突破,哪些瓶颈不容易突破等。所谓存储优化,其目的就在于发挥硬件的极限性能。而好的容量规划,有利于我们决定机器配置,从而把不必要的浪费降到最小。

什么是容量规划?

我们讨论的存储,说到底都是基于操作系统之上的一个应用软件,而操作系统能利用的,无非是系统的存储:磁盘、内存、CPU cache等等。所以容量规划的意义就是:按要存储的数据特点,针对一段时间的数据量,对机器各个存储的容量、性能及系统配置进行合理预估。

通常这个问题在实际容量规划中可以化简为对内存,硬盘容量和性能的预估。

下面我们就以MongoDB为例说一下容量预估的一些计算方法。我们通常的一个粗糙的要求是要将所有热数据放到内存中。这里的热数据可能包括经常访问的数据,索引和系统开销。下面我们就这三个方面进行说明:

常访问的数据

根据不同的应用场景,你可以对数据访问情况进行预估。比如用MongoDB保存帖子内容,每个帖子大小为1k,目前有1亿个帖子,每天新增100w个帖子,那么3个月后帖子量大概为2亿,需要200G的硬盘空间。

每天新增的100w帖子是常访问的,而可能我们每天活跃访问的贴子为200w,也就是说另外100w是之前的老帖子。如果我们规划给热数据的内存大小为1G,那只能装下100w数据,装不了200w数据。由于帖子访问的随机性,最坏的情况是我们每次访问的数据都不在内存中(比如先访问了不在内存中的100w,加载到内存中,再访问刚刚被换到磁盘上的数据,又需要再加载一次),需要进行和PV相同次数的磁盘IO,灾难!最好的情况我们也需要100w次磁盘IO(比如先对在内存中的100w数据进行频繁访问,再对不在内存中的100w数据进行频繁访问),在访问频率均匀的情况下,每秒需要进行大概12次的磁盘IO。

那我们把规划给热数据的内存大小调为2G,看看会如何,这时候一天200w热数据正好能装下。那么最好的情况下,需要进行100w次磁盘IO(比如200w数据中的100w老数据全都在昨天的热数据中,则只需要对100w数据进行重新加载),在访问频率均匀的情况下,每秒需要进行大概12次的磁盘IO。最坏的情况下,需要进行200w次磁盘IO(比如今天访问的200w条数据和昨天的热数据没有重合),在访问频率均匀的情况下,每秒需要进行大概25次的磁盘IO。

同理,我们再增大内存,会需要访问的数据在内存中的机率增大,从而减小磁盘IO的频率。

上面说的是一个简单例子,具体你可以根据自己的数据访问特性进行评估和计算,而且不仅要算平均IO,更重要的是巅峰IO。

同时不要忘了,MongoDB还会定时调用fsync将内存中的脏页flush到磁盘(默认一分钟一次),你可以根据你自己脏数据的量或者比例来评估每次的IO,然后你再考虑是否需要将fsync的频率调低一点。

如果你还开启了journaling log,那这个IO量也需要加进去。

当然,接下来的就是你的磁盘是否能够承受最终的IO量,然后你可以考虑你是否需要使用更快的硬盘,是否需要RAID,是否需要换用SSD等等了。

索引量

索引和常访问数据不同,索引要求全部放在内存中,所以索引的容量计算就相对容易很多。通过MongoDB的db.stats()命令就能看到你当前占用的索引大小。比如上面的例子,现在1亿条数据如果索引大小为5G的话,那么2亿条的时候大概需要10G。所以内存必须要装下这10G索引。

系统开销

MongoDB daemon的开销基本可以理解为一个常数,所以这里的系统开销就主要是连接开销。这取决于你的应用特点。比如你最大的并发操作为100。也就是同时100个连接与MongoDB相连。每个连接一个线程开销为系统的stack size设置,默认是10M,那就是1G(当然你可以适当调整这个值)。需要对数据进行实时排序的话,需要再算上排序时的内存开销。

总结

当然,上面讲的是一个简单的预估方法,我们不期望能够通过计算得出真实的容量估算结果,毕竟互联网产品的变化总是那么不可控。但是在部署前按业务情况进行相关的容量预估是非常重要的。好的预估可以在金钱、性能和运维成本上得到一个相对平衡的结果。

相关文章:

详解MongoDB的Compact操作

MongoDB JavaScript Driver 测试

CakePHP中的MongoDB使用

10gen发布MongoDB监控系统MMS

Mongodb Mapreduce 初窥
无觅

相关 [mongodb 容量 规划] 推荐:

MongoDB容量规划

- gOODiDEA - NoSQLFan
上周在公司做了一个NoSQL和MongoDB相关的技术分享,会后有同事问及MongoDB对内存需求的问题,做了简单回复. 今天就写篇文章对MongoDB容量规划做一个比较详细的总结. 首先我们要问一个很傻的问题:存储是什么. 存储就是用来装数据的东西,它需要满足以下两点基本需求:. 基于这两点,我们需要问的问题就是,这个存储能够存多少数据,能够提供多高的写入速度,能够提供多高的读取速度.

Redis容量及使用规划

- - 互联网旁观者
在使用Redis过程中,我们发现了不少Redis不同于Memcached,也不同于MySQL的特征. (本文主要讨论Redis未启用VM支持情况). MySQL: 需事先设计. Memcached: 无需设计. Redis: 小型系统可以不用,但是如果要合理的规划及使用Redis,需要事先进行类似如下一些规划.

[mongodb] java操作mongodb

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

【MongoDB】MongoDB之优化器Profiler

- - CSDN博客数据库推荐文章
在mysql数据库中,慢查询日志经常作为优化数据库的依据, mongodb中依然有类似的功能. Mongodb自带的profiler,可以方便地记录所有耗时的操作,以便于调优;. 一、开始profiler功能. 开启profier功能有两种:. 第一种就是直接在启动参数里面进行设置,就在茄冬mongodb时候添加-profile=级别.

夜说mongodb

- Lianhui Wang - NoSQLFan
前两天本站刚刚分享了wordnik使用MongoDB经验的文章:《Wordnik 的 MongoDB 使用经历》,今天又看到一位朋友对这方面做的总结,分享在这里,供大家参考. 赋闲以后很长没有更新博客了,说忙完全是借口,多半因为没有兴致所致. 今天凌晨比赛多多,趁着比赛的前奏和间隙,遂浏览些技术文章.

MongoDB与内存

- 高春辉 - 火丁笔记
但凡初次接触MongoDB的人,无不惊讶于它对内存的贪得无厌,至于个中缘由,我先讲讲Linux是如何管理内存的,再说说MongoDB是如何使用内存的,答案自然就清楚了. 据说带着问题学习更有效,那就先看一个MongoDB服务器的top命令结果:. 这台MongoDB服务器有没有性能问题. 先讲讲Linux是如何管理内存的.

白话MongoDB(一)

- Ease - 江边潮未尽,枫红一季秋
按照官方的说法,MongoDB是一种可扩展的高性能的开源的面向文档(document-oriented )的数据库,采用C++开发. 注意mongo不是mango(芒果),这个词是从humongous中截取出来的,其野心不言而明,直指海量数据存储. 和其他很多NoSQL不太一样,MongoDB背后有一个专门的商业公司在提供支持和推广,有点类似MySQL AB的模式.

MongoDB 索引

- - 博客园_首页
索引是用来加快查询的,数据库索引与数据的索引类似,有了索引就不需要翻遍整本书,数据库可以直接在索引中查找,. 使得查询速度很快,在索引中找到条目后,就可以直接跳转到目标文档的位置.. 要掌握如何为查询配置最佳索引会有些难度.. MongoDB索引几乎和关系型数据库的索引一样.绝大数优化关系型数据库索引的技巧同样适用于MongoDB..

MongoDB sql操作

- - 数据库 - ITeye博客
1.  基本查询:. 下面的示例等同于SQL语句的where name = "stephen" and age = 35.      --返回指定的文档键值对. 下面的示例将只是返回name和age键值对.      --指定不返回的文档键值对. 下面的示例将返回除name之外的所有键值对.