`
vipshichg
  • 浏览: 267479 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

把MongoDB当成纯内存数据库使用

阅读更多

这种用法对于以下应用场合来讲,超实用:

置于慢速RDBMS系统之前的写操作密集型高速缓存

嵌入式系统

无需持久化数据的PCI兼容系统

需要轻量级数据库而且库中数据可以很容易清除掉的单元测试(unit testing)

如果这一切可以实现就真是太优雅了:我们就能够巧妙地在不涉及磁盘操作的情况下利用MongoDB的查询/检索功能。可能你也知道,在99%的情况下,磁盘IO(特别是随机IO)是系统的瓶颈,而且,如果你要写入数据的话,磁盘操作是无法避免的。

MongoDB有一个非常酷的设计决策,就是她可以使用内存影射文件(memory-mapped file)来处理对磁盘文件中数据的读写请求。这也就是说,MongoDB并不对RAM和磁盘这两者进行区别对待,只是将文件看作一个巨大的数组,然后按照字节为单位访问其中的数据,剩下的都交由操作系统(OS)去处理!就是这个设计决策,才使得MongoDB可以无需任何修改就能够运行于RAM之中。

实现方法

这一切都是通过使用一种叫做tmpfs的特殊类型文件系统实现的。在Linux中它看上去同常规的文件系统(FS)一样,只是它完全位于RAM中(除非其大小超过了RAM的大小,此时它还可以进行swap,这个非常有用!)。我的服务器中有32GB的RAM,下面让我们创建一个16GB的 tmpfs:

  1. # mkdir /ramdata 
  2. # mount -t tmpfs -o size=16000M tmpfs /ramdata/ 
  3. # df 
  4. Filesystem           1K-blocks      Used Available Use% Mounted on 
  5. /dev/xvde1             5905712   4973924    871792  86% / 
  6. none                  15344936         0  15344936   0% /dev/shm 
  7. tmpfs                 16384000         0  16384000   0% /ramdata 

接下来要用适当的设置启动MongoDB。为了减小浪费的RAM数量,应该把smallfiles和noprealloc设置为true。既然现在是基于RAM的,这么做完全不会降低性能。此时再使用journal就毫无意义了,所以应该把nojournal设置为true。

  1. dbpath=/ramdata 
  2. nojournal = true 
  3. smallFiles = true 
  4. noprealloc = true 

MongoDB启动之后,你会发现她运行得非常好,文件系统中的文件也正如期待的那样出现了:

  1. # mongo 
  2. MongoDB shell version: 2.3.2 
  3. connecting to: test 
  4. > db.test.insert({a:1}) 
  5. > db.test.find() 
  6. { "_id" : ObjectId("51802115eafa5d80b5d2c145"), "a" : 1 } 
  7. # ls -l /ramdata/ 
  8. total 65684 
  9. -rw-------. 1 root root 16777216 Apr 30 15:52 local.0 
  10. -rw-------. 1 root root 16777216 Apr 30 15:52 local.ns 
  11. -rwxr-xr-x. 1 root root        5 Apr 30 15:52 mongod.lock 
  12. -rw-------. 1 root root 16777216 Apr 30 15:52 test.0 
  13. -rw-------. 1 root root 16777216 Apr 30 15:52 test.ns 
  14. drwxr-xr-x. 2 root root       40 Apr 30 15:52 _tmp 

现在让我们添加一些数据,证实一下其运行完全正常。我们先创建一个1KB的document,然后将它添加到MongoDB中4百万次:

  1. > str = "" 
  2. > aaa = "aaaaaaaaaa" 
  3. aaaaaaaaaa 
  4. > for (var i = 0; i < 100; ++i) { str += aaa; } 
  5. > for (var i = 0; i < 4000000; ++i) { db.foo.insert({a: Math.random(), s: str});} 
  6. > db.foo.stats() 
  7.         "ns" : "test.foo", 
  8.         "count" : 4000000, 
  9.         "size" : 4544000160, 
  10.         "avgObjSize" : 1136.00004, 
  11.         "storageSize" : 5030768544, 
  12.         "numExtents" : 26, 
  13.         "nindexes" : 1, 
  14.         "lastExtentSize" : 536600560, 
  15.         "paddingFactor" : 1, 
  16.         "systemFlags" : 1, 
  17.         "userFlags" : 0, 
  18.         "totalIndexSize" : 129794000, 
  19.         "indexSizes" : { 
  20.                 "_id_" : 129794000 
  21.         }, 
  22.         "ok" : 1 

可以看出,其中的document平均大小为1136字节,数据总共占用了5GB的空间。_id之上的索引大小为130MB。现在我们需要验证一件 非常重要的事情:RAM中的数据有没有重复,是不是在MongoDB和文件系统中各保存了一份?还记得MongoDB并不会在她自己的进程内缓存任何数据,她的数据只会缓存到文件系统的缓存之中。那我们来清除一下文件系统的缓存,然后看看RAM中还有有什么数据:

  1. # echo 3 > /proc/sys/vm/drop_caches  
  2. # free 
  3.              total       used       free     shared    buffers     cached 
  4. Mem:      30689876    6292780   24397096          0       1044    5817368 
  5. -/+ buffers/cache:     474368   30215508 
  6. Swap:            0          0          0 

可以看到,在已使用的6.3GB的RAM中,有5.8GB用于了文件系统的缓存(缓冲区,buffer)。为什么即使在清除所有缓存之后,系统中仍然还有5.8GB的文件系统缓存??其原因是,Linux非常聪明,她不会在tmpfs和缓存中保存重复的数据。太棒了!这就意味着,你在RAM只有一份数据。下面我们访问一下所有的document,并验证一下,RAM的使用情况不会发生变化:

  1. > db.foo.find().itcount() 
  2. 4000000 
  3. # free 
  4.              total       used       free     shared    buffers     cached 
  5. Mem:      30689876    6327988   24361888          0       1324    5818012 
  6. -/+ buffers/cache:     508652   30181224 
  7. Swap:            0          0          0 
  8. # ls -l /ramdata/ 
  9. total 5808780 
  10. -rw-------. 1 root root  16777216 Apr 30 15:52 local.0 
  11. -rw-------. 1 root root  16777216 Apr 30 15:52 local.ns 
  12. -rwxr-xr-x. 1 root root         5 Apr 30 15:52 mongod.lock 
  13. -rw-------. 1 root root  16777216 Apr 30 16:00 test.0 
  14. -rw-------. 1 root root  33554432 Apr 30 16:00 test.1 
  15. -rw-------. 1 root root 536608768 Apr 30 16:02 test.10 
  16. -rw-------. 1 root root 536608768 Apr 30 16:03 test.11 
  17. -rw-------. 1 root root 536608768 Apr 30 16:03 test.12 
  18. -rw-------. 1 root root 536608768 Apr 30 16:04 test.13 
  19. -rw-------. 1 root root 536608768 Apr 30 16:04 test.14 
  20. -rw-------. 1 root root  67108864 Apr 30 16:00 test.2 
  21. -rw-------. 1 root root 134217728 Apr 30 16:00 test.3 
  22. -rw-------. 1 root root 268435456 Apr 30 16:00 test.4 
  23. -rw-------. 1 root root 536608768 Apr 30 16:01 test.5 
  24. -rw-------. 1 root root 536608768 Apr 30 16:01 test.6 
  25. -rw-------. 1 root root 536608768 Apr 30 16:04 test.7 
  26. -rw-------. 1 root root 536608768 Apr 30 16:03 test.8 
  27. -rw-------. 1 root root 536608768 Apr 30 16:02 test.9 
  28. -rw-------. 1 root root  16777216 Apr 30 15:52 test.ns 
  29. drwxr-xr-x. 2 root root        40 Apr 30 16:04 _tmp 
  30. # df 
  31. Filesystem           1K-blocks      Used Available Use% Mounted on 
  32. /dev/xvde1             5905712   4973960    871756  86% / 
  33. none                  15344936         0  15344936   0% /dev/shm 
  34. tmpfs                 16384000   5808780  10575220  36% /ramdata 

果不其然! :)

复制(replication)呢?

既然服务器在重启时RAM中的数据都会丢失,所以你可能会想使用复制。采用标准的副本集(replica set)就能够获得自动故障转移(failover),还能够提高数据读取能力(read capacity)。如果有服务器重启了,它就可以从同一个副本集中另外一个服务器中读取数据从而重建自己的数据(重新同步,resync)。即使在大量数据和索引的情况下,这个过程也会足够快,因为索引操作都是在RAM中进行的 :)

有一点很重要,就是写操作会写入一个特殊的叫做oplog的collection,它位于local数据库之中。缺省情况下,它的大小是总数据量的5%。在我这种情况下,oplog会占有16GB的5%,也就是800MB的空间。在拿不准的情况下,比较安全的做法是,可以使用oplogSize这个选项为oplog选择一个固定的大小。如果备选服务器宕机时间超过了oplog的容量,它就必须要进行重新同步了。要把它的大小设置为1GB,可以这样:

oplogSize = 1000

分片(sharding)呢?

既然拥有了MongoDB所有的查询功能,那么用它来实现一个大型的服务要怎么弄?你可以随心所欲地使用分片来实现一个大型可扩展的内存数据库。配置服务器(保存着数据块分配情况)还还是用过采用基于磁盘的方案,因为这些服务器的活动数量不大,老从头重建集群可不好玩。

注意事项

RAM属稀缺资源,而且在这种情况下你一定想让整个数据集都能放到RAM中。尽管tmpfs具有借助于磁盘交换(swapping)的能力,但其性能下降将非常显著。为了充分利用RAM,你应该考虑:

使用usePowerOf2Sizes选项对存储bucket进行规范化

定期运行compact命令或者对节点进行重新同步(resync)

schema的设计要相当规范化(以避免出现大量比较大的document)

结论

宝贝,你现在就能够将MongoDB用作内存数据库了,而且还能使用她的所有功能!性能嘛,应该会相当惊人:我在单线程/核的情况下进行测试,可以达到每秒20K个写入的速度,而且增加多少个核就会再增加多少倍的写入速度。

2
5
分享到:
评论
1 楼 jnoee 2013-09-24  
为何不用redis?

相关推荐

    mongoDB非关系型数据库安装以及使用指南

    MongoDB是NoSQL数据库的一种,不使用传统的关系型数据库表格和列结构,而是使用键值对、文档、集合和数据库的概念。 二、MongoDB安装步骤 1. 下载安装包:访问MongoDB官方网站...

    mongodb 数据库基本操作.doc

    - **使用`use`命令**:在MongoDB shell中,可以使用`use`命令来选择一个数据库或创建一个新的数据库。例如: ```shell use mydatabase ``` 上述命令会创建(或选择)名为`mydatabase`的数据库。 #### 三、插入...

    基于mongodb数据库的集成redis缓存springboot实战

    MongoDB是一种分布式文档型数据库,它以JSON格式的文档存储数据,灵活性高,适合处理大量非结构化或半结构化数据。SpringBoot是Java开发框架,简化了Spring应用的初始搭建以及开发过程,提供了自动配置、起步依赖等...

    FineReport如何连接和使用MongoDB数据库

    随着NoSQL数据库越来越流行,MongoDB数据库作为NoSQL数据库中的领头羊,使用也越来越广泛。为此,FineReport V8.0版本提供了数据连接和数据集接口,可以通过开发一款可以连接和使用的MongoDB数据库的插件。

    同步Mongodb数据库.zip_MongoDB_Mongodb 同步数据库

    1. 高性能:MongoDB使用内存映射技术,数据读写速度快。 2. 高可用性:通过复制集实现数据备份和故障切换。 3. 易扩展性:支持水平扩展,通过分片集群处理大数据量。 4. 强大的查询语言:支持丰富的查询表达式和聚合...

    dbeaver21.1-enterprise-agent用于连接MongoDB等NoSQL类型数据库

    6. **性能监控**:实时监控数据库性能,包括查询执行时间、内存使用情况等,有助于优化数据库性能。 7. **备份与恢复**:提供数据备份和恢复功能,确保数据安全。 8. **扩展插件**:拥有丰富的插件生态系统,用户...

    mongoDB分布式文件存储的数据库

    MongoDB是一种基于分布式文件存储的开源数据库系统,它在处理大量数据时表现出高效、可扩展性和高可用性。MongoDB采用JSON(JavaScript Object Notation)文档格式存储数据,这种格式灵活且易于理解,使得它在大数据...

    mongoDB非关系型数据库客户端软件

    1. 文档型数据模型:MongoDB使用BSON(Binary JSON)文档存储数据,这种格式支持嵌套结构和数组,适合处理复杂的数据结构。 2. 分布式架构:MongoDB支持分片(sharding)和复制集(replica sets),能够轻松实现...

    mongodb数据库管理工具

    5. **性能监控**:显示数据库的性能指标,如CPU使用率、内存占用、I/O活动等,帮助优化数据库性能。 6. **备份与恢复**:提供一键式备份和恢复功能,简化了MongoDB的数据保护流程。 7. **用户管理**:可以方便地...

    MongoDB数据库文件-名言警句集合,导入即可使用

    MongoDB数据库文件-名言警句集合,导入即可使用 MongoDB数据库文件-名言警句集合,导入即可使用 MongoDB数据库文件-名言警句集合,导入即可使用 MongoDB数据库文件-名言警句集合,导入即可使用 MongoDB数据库文件-...

    MongoDB 数据库-四书五经-中庸,导入直接使用

    MongoDB 数据库-四书五经-中庸,导入直接使用 MongoDB 数据库-四书五经-中庸,导入直接使用 MongoDB 数据库-四书五经-中庸,导入直接使用 MongoDB 数据库-四书五经-中庸,导入直接使用 MongoDB 数据库-四书五经-中庸...

    MongoDB数据库

    作为NoSQL数据库的一种,MongoDB不采用传统的表格和列式数据模型,而是使用键值对、文档、集合和数据库的结构来存储数据,这使得它在处理JSON、XML等半结构化和非结构化数据时表现出色。 MongoDB的主要特点包括: ...

    MongoDB数据库-四书五经-孟子

    MongoDB数据库-四书五经-孟子,导入即可使用 MongoDB数据库-四书五经-孟子,导入即可使用 MongoDB数据库-四书五经-孟子,导入即可使用 MongoDB数据库-四书五经-孟子,导入即可使用 MongoDB数据库-四书五经-孟子,...

    使用mongodb+koa模拟数据库请求.zip

    mongodb 数据库基本操作 1、mongoDB的介绍 mongoDB是一个基于分布式文件存储的数据库,由 C++ 语言编写,旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。它介于关系数据库和非关系数据库之间,被认为是非...

    mongodb和redis数据库文档

    MongoDB虽然不是内存数据库,但通过优化也能达到较高的性能。 3. 扩展性:MongoDB通过分片集群实现水平扩展,适合大数据量场景;Redis则依赖主从复制和Redis Cluster实现扩展,但扩展性相对有限。 4. 使用场景:...

    mongodb 非关系型数据库

    MongoDB 是一个流行的开源、非关系型数据库系统,它属于NoSQL数据库的一种,以其灵活性、高性能和可扩展性而受到广泛关注。MongoDB的设计理念是处理大量数据并支持高并发读写操作,尤其适合于需要存储半结构化或结构...

    MongoDB数据库简单介绍

    MongoDB是一款开源、基于分布式文件存储的NoSQL数据库系统,它使用C++语言编写。与传统的关系型数据库不同,MongoDB采用文档数据模型来存储数据,这种数据模型非常灵活,能够很好地适应快速变化的数据结构需求。文档...

    最像关系型数据库的NoSQL---MongoDb

    MongoDb是非关系型数据库的一种,它是一种基于分布式的文档型数据库。

    MongoDB(1)数据库

    MongoDB(1)数据库的详细介绍,

    MongoDB数据库管理工具

    5. 查询语言:MongoDB使用MQL(MongoDB Query Language)进行查询,它具有丰富的查询选项,如条件查询、聚合操作等。 MongoVUE作为MongoDB的管理工具,主要功能包括: 1. 连接管理:MongoVUE可以连接到本地或远程...

Global site tag (gtag.js) - Google Analytics