mongo内部培训

 

Linux是如何管理内存的

 

shell> top -p $(pidof mongod)

Mem: 32872124k total, 30065320k used, 2806804k free,   245020k buffers

Swap: 2097144k total,      100kused,  2097044k free, 26482048k cached

 

 VIRT RES  SHR %MEM

1892g 21g  21g 69.6

 

shell> free -m
             total       used       free     shared    buffers     cached
Mem:         32101      29377       2723          0        239      25880
-/+ buffers/cache:       3258      28842
Swap:         2047          0       2047

看到used一栏数值偏大,free一栏数值偏小,往往会认为内存要用光了。其实并非如此,之所以这样是因为每当我们操作文件的时候,Linux都会尽可能的把文件缓存到内存里,这样下次访问的时候,就可以直接从内存中取结果,所以cached一栏的数值非常的大,不过不用担心,这部分内存是可回收的,操作系统的虚拟内存管理器会按照LRU算法淘汰冷数据。还有一个buffers,也是可回收的,不过它是保留给块设备使用的。

 

知道了原理,我们就可以推算出系统可用的内存是free + buffers + cached

shell> echo $((2723 + 239 + 25880))
28842

至于系统实际使用的内存是used – buffers – cached:

shell> echo $((29377 - 239 - 25880))
3258

 

MongoDB是如何使用内存的

目前,MongoDB使用的是内存映射存储引擎,它会把数据文件映射到内存中,如果是读操作,内存中的数据起到缓存的作用,如果是写操作,内存还可以把随机的写操作转换成顺序的写操作,总之可以大幅度提升性能。MongoDB并不干涉内存管理工作,而是把这些工作留给操作系统的虚拟内存管理器去处理,这样做的好处是简化了MongoDB的工作,但坏处是你没有方法很方便的控制MongoDB占多大内存,幸运的是虚拟内存管理器的存在让我们多数时候并不需要关心这个问题。

可以通过mongostat命令来监控MongoDB的内存使用情况,如下所示:

shell> mongostat

mapped vsize    res faults

 940g  1893g  21.9g     0

其中内存相关字段的含义是:

·        mapped:映射到内存的数据大小

·        visze:占用的虚拟内存大小

·        res:占用的物理内存大小

注:如果操作不能在内存中完成,结果faults列的数值不会是0,视大小可能有性能问题。

到底MongoDB配备多大内存合适?宽泛点来说,多多益善,如果要确切点来说,这实际取决于你的数据及索引的大小,内存如果能够装下全部数据加索引是最佳情况,不过很多时候,数据都会比内存大,比如本文所涉及的MongoDB实例:

mongo> db.stats()
{
    "dataSize" : 1004862191980,
    "indexSize" : 1335929664
}

本例中索引只有1G多,内存完全能装下,而数据文件则达到了1T,估计很难找到这么大内存,此时保证内存能装下热数据即可,至于热数据是多少,取决于具体的应用,你也可以通过观察faults的大小来判断当前内存是否能够装下热数据,如果faults持续变大,就说明当前内存已经不能满足热数据的大小了。如此一来内存大小就明确了:内存 > 索引 + 热数据,最好有点富余,毕竟操作系统本身正常运转也需要消耗一部分内存。

关于MongoDB与内存的话题,大家还可以参考官方文档中的相关介绍。

 

容量规划

容量规划的意义就是:按要存储的数据特点,针对一段时间的数据量,对机器各个存储的容量、性能及系统配置进行合理预估。

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

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

常访问的数据

根据不同的应用场景,你可以对数据访问情况进行预估。

比如用MongoDB保存帖子内容,每个帖子大小为1k,目前有1亿个帖子,每天新增100w个帖子,那么3个月后帖子量大概为2亿,需要200G的硬盘空间。

每天新增的100w帖子是常访问的,而可能我们每天活跃访问的贴子为200w,也就是说另外100w是之前的老帖子。如果我们规划给热数据的内存大小为1G,那只能装下100w数据,装不了200w数据。由于帖子访问的随机性,最坏的情况是我们每次访问的数据都不在内存中

索引量

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

系统开销

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

MongoDB与硬盘

磁盘占用

总的来说mongodb占用磁盘空间比数据本身大3倍。以现场为例,mysql占用为77GB,预计导入到mongodb后磁盘占用为230G。

 

先进行仿真数据下的测试,首先需要清楚你业务中的数据结构在存储时的膨胀率如何。然后才是按照数据结构计算存储容量。

 

MySQL和MongoDB设计实例对比

{

"_id" : ObjectId("52ca53d46cebc237c868a9b9"),

"adm__dt" : ISODate("2013-08-01T14:09:59.000+08:00"),

"adm_dcs" : "a:1:{i:0;s:3:\"280\";}",

"adm_dep" : "",

"adm_email" : "sdsdff@12.com",

"adm_id" : 82,

"adm_last_login_ip" : "192.168.9.38",

"adm_last_login_time" : 1394695621,

"adm_login_times" : NumberLong(240),

"adm_memo" : "",

"adm_name" : "mpf",

"adm_no" : "",

"adm_pwd" : "e10adc3949ba59abbe56e057f20f883e",

"adm_role" : "YToyOntzOjQ6InR5cGUiO3M6Mzoib3B0IjtzOjM6Im9wdCI7YToxOntpOjA7czoxOiIxIjt9fQ==",

"adm_status" : "enable",

"adm_uid" : "mpf",

"disabled" : "false"

}

 

{

"_id" : ObjectId("530ae8a0e4b052f271d56a91"),

"auth_isRoot" : false,

"auth_login_times" : 5,

"auth_pwd" : "aaaaaa",

"auth_role_ids[]" : [

    "52e257e1e4b0bbe3becfce84",

    "530aef2be4b05287103191e2"

],

"auth_role_refs" : [

    {

        "$ref" : "__admin_role",

        "$id" : ObjectId("52e257e1e4b0bbe3becfce84")

    },

    {

        "$ref" : "__admin_role",

        "$id" : ObjectId("530aef2be4b05287103191e2")

    }

],

"auth_status" : true,

"auth_uid" : "aaaaaa",

"create_time" : ISODate("2014-02-24T14:37:20.842+08:00"),

"disabled" : false,

"last_auth_date" : ISODate("2014-03-03T10:17:37.221+08:00"),

"last_auth_ip" : "192.168.9.13",

"modify_time" : ISODate("2014-03-03T10:10:06.208+08:00"),

"user_dep" : "",

"user_email" : "",

"user_memo" : "",

"user_name" : "fdsgf",

"user_no" : ""

}

 

 

UPM数据模型的特点

1.      一条关系线上存在多个多对多。

在数据库层的表达形态一般为拆分成两个1对多。多方都有引用关系。

2.      统计方法。

入库时及时统计,展现做简单统计。

例1:故障率的实现为:

每个上报的警报会单独在“警报触发时间”表中记录,每个秒时间点唯一。需要展现时,只需做简单的个数统计即可。

例2:应用警报统计:

         每个上报的警报会及时的做次数统计。分别在1分钟,1小时,1天为时间段。

3.      UPM中数据库与java模型的实例化方法。

在UPM项目中,java模型可以很方便的与数据库中的数据做相互转换,极大的提高了开发效率。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值