游戏服务器使用MongoDB作为mongodb 数据库设计,还有必要使用Redis缓存吗

把 MongoDB 当成是纯内存数据库来使用(Redis 风格) - 技术翻译 - 开源中国社区
把 MongoDB 当成是纯内存数据库来使用(Redis 风格)
【已翻译100%】
英文原文:
推荐于 4年前 (共 5 段, 翻译完成于 05-04)
参与翻译&(1人)&:
将MongoDB用作内存数据库(in-memory database),也即,根本就不让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:
# mkdir /ramdata
# mount -t tmpfs -o size=16000M tmpfs /ramdata/
Filesystem
Used Available Use% Mounted on
/dev/xvde1
0% /dev/shm
0% /ramdata
接下来要用适当的设置启动MongoDB。为了减小浪费的RAM数量,应该把smallfiles和noprealloc设置为true。既然现在是基于RAM的,这么做完全不会降低性能。此时再使用journal就毫无意义了,所以应该把nojournal设置为true。
dbpath=/ramdata
nojournal = true
smallFiles = true
noprealloc = true
MongoDB启动之后,你会发现她运行得非常好,文件系统中的文件也正如期待的那样出现了:
MongoDB shell version: 2.3.2
connecting to: test
& db.test.insert({a:1})
& db.test.find()
{ "_id" : ObjectId("eafa5d80b5d2c145"), "a" : 1 }
# ls -l /ramdata/
total 65684
-rw-------. 1 root root
Apr 30 15:52 local.0
-rw-------. 1 root root
Apr 30 15:52 local.ns
-rwxr-xr-x. 1 root root
5 Apr 30 15:52 mongod.lock
-rw-------. 1 root root
Apr 30 15:52 test.0
-rw-------. 1 root root
Apr 30 15:52 test.ns
drwxr-xr-x. 2 root root
40 Apr 30 15:52 _tmp
现在让我们添加一些数据,证实一下其运行完全正常。我们先创建一个1KB的document,然后将它添加到MongoDB中4百万次:
& str = ""
& aaa = "aaaaaaaaaa"
aaaaaaaaaa
& for (var i = 0; i & 100; ++i) { str += }
& for (var i = 0; i & 4000000; ++i) { db.foo.insert({a: Math.random(), s: str});}
& db.foo.stats()
"ns" : "test.foo",
"count" : 4000000,
"size" : ,
"avgObjSize" : ,
"storageSize" : ,
"numExtents" : 26,
"nindexes" : 1,
"lastExtentSize" : ,
"paddingFactor" : 1,
"systemFlags" : 1,
"userFlags" : 0,
"totalIndexSize" : ,
"indexSizes" : {
&翻译得不错哦!
可以看出,其中的document平均大小为1136字节,数据总共占用了5GB的空间。_id之上的索引大小为130MB。现在我们需要验证一件
非常重要的事情:RAM中的数据有没有重复,是不是在MongoDB和文件系统中各保存了一份?还记得MongoDB并不会在她自己的进程内缓存任何数据,她的数据只会缓存到文件系统的缓存之中。那我们来清除一下文件系统的缓存,然后看看RAM中还有有什么数据:
# echo 3 & /proc/sys/vm/drop_caches
-/+ buffers/cache:
可以看到,在已使用的6.3GB的RAM中,有5.8GB用于了文件系统的缓存(缓冲区,buffer)。为什么即使在清除所有缓存之后,系统中仍然还有5.8GB的文件系统缓存??其原因是,Linux非常聪明,她不会在tmpfs和缓存中保存重复的数据。太棒了!这就意味着,你在RAM只有一份数据。下面我们访问一下所有的document,并验证一下,RAM的使用情况不会发生变化:
& db.foo.find().itcount()
-/+ buffers/cache:
# ls -l /ramdata/
total 5808780
-rw-------. 1 root root
Apr 30 15:52 local.0
-rw-------. 1 root root
Apr 30 15:52 local.ns
-rwxr-xr-x. 1 root root
5 Apr 30 15:52 mongod.lock
-rw-------. 1 root root
Apr 30 16:00 test.0
-rw-------. 1 root root
Apr 30 16:00 test.1
-rw-------. 1 root root
Apr 30 16:02 test.10
-rw-------. 1 root root
Apr 30 16:03 test.11
-rw-------. 1 root root
Apr 30 16:03 test.12
-rw-------. 1 root root
Apr 30 16:04 test.13
-rw-------. 1 root root
Apr 30 16:04 test.14
-rw-------. 1 root root
Apr 30 16:00 test.2
-rw-------. 1 root root
Apr 30 16:00 test.3
-rw-------. 1 root root
Apr 30 16:00 test.4
-rw-------. 1 root root
Apr 30 16:01 test.5
-rw-------. 1 root root
Apr 30 16:01 test.6
-rw-------. 1 root root
Apr 30 16:04 test.7
-rw-------. 1 root root
Apr 30 16:03 test.8
-rw-------. 1 root root
Apr 30 16:02 test.9
-rw-------. 1 root root
Apr 30 15:52 test.ns
drwxr-xr-x. 2 root root
40 Apr 30 16:04 _tmp
Filesystem
Used Available Use% Mounted on
/dev/xvde1
0% /dev/shm
% /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个写入的速度,而且增加多少个核就会再增加多少倍的写入速度。
&翻译得不错哦!
我们的翻译工作遵照 ,如果我们的工作有侵犯到您的权益,请及时联系我们
我又重新看了一下原文,感觉这个翻译的确会有点问题,原文的意思貌似是每秒20k次写入,而不是我翻译的可能会让人领会为每秒20kB的写入速度
原理上可以这么说,但有些数据库在设计时并未考虑使用内存作为文件系统,它们在保存数据时除了保存用户数据之外还会保存大量的衍生数据,使得这样的数据库作为内存数据库使用时内存使用效率极其低下,所以拿它们来做内存数据库就相当不合适了。
可能在查询功能和索引方面MonogoDB会略胜一筹?
嗯,这种用法只能是在适当的场合下使用。不过我感觉在集群中使用应该算是相当可靠了
和键值对还是很大区别的。我们数据库做键值对应用,单核的检索是400万行/秒。redis其实是个效率很低的东西。
redis...记不清了,不好意思
和键值对还是很大区别的。我们数据库做键值对应用,单核的检索是400万行/秒。redis其实是个效率很低的东西。啊??
和键值对还是很大区别的。我们数据库做键值对应用,单核的检索是400万行/秒。redis其实是个效率很低的东西。啊??求对比/分析报告
表现一下而已,国货当自强轻松享有高性能企业级云服务器
支持五天无理由退款,100倍事故赔偿,1V1专席秘书
高性价比一站式托管服务
专业定制托管方案,低资费,独享带宽,资源弹性扩张
工程师在线为您排忧解难
全程监管,安心托付,企业部署更轻松
缓存数据库到底哪家强?Memcached还是Redis?
  要memcached还是要redis?在构建一款现代且由数据库驱动的web应用程序并希望使其拥有更为出色的性能表现时,这个问题总会时不时出现、并给每一位开发人员带来困扰。在考虑对应用程序的性能表现进行提升时,缓存机制往往是解决问题的重要起点,而memcached与redis则经常被作为初步方案来加以比较。
  这两套声名显赫的缓存引擎拥有着诸多相似之处,但它们同样也具备大量显著差异。作为二者当中更年轻也更加灵活的方案,redis被大部分技术人员视为首选目标――但请别掉以轻心,不容忽视的重要例外情况也是客观存在的。
  两者相似之处
  让我们先从二者的相似之处谈起。memcached与redis都属于内存内、键值数据存储方案。它们都从属于数据管理解决方案中的nosql家族,而且都基于同样的键值数据模型。双方都选择将全部数据保存在内存当中,这自然也就让它们成为非常理想的缓冲层实现方案。从性能表现的角度来看,两类数据存储机制也具备诸多共通性,包括拥有几乎相同的特征(与指标)表现、而且高度关注工作负载的数据吞吐量与延迟状况。
  除了同为内存内键值数据存储方案,memcached与redis还都是相当成熟而且极具人气的开源项目。memcached最初是由brad
fitzpatrick于2003年开发而成,当时其直接服务对象为livejournal交友网站。在此之后,memcached被重新用c语言进行了编写(其最初实现方式为perl语言)且投身于公共领域,并在这里逐步发展为现代web应用程序的构建基石。memcached项目的当前开发工作主要关注其运行稳定性及优化效果方面,而不再积极为其打造更多新型功能。
  redis则由salvatore
sanfilippo于2009年创建,而且时至今日sanfilippo仍然担任着该项目的首席开发者以及惟一维护者的角色。redis有时候会被人们称为“强化版的memcached”。考虑到从memcached身上吸取并借鉴到大量宝贵的经验教训,这样的评价其实并不令人意外。redis在功能多样性方面要胜过memcached,这虽然让者更为强大也更具灵活性、但其复杂程度也较后者为甚。
  作为两套被众多企业采纳并部署在无数关键性生产任务环境当中的解决方案,memcached与redis在任何一种可行性编程语言领域都拥有能够提供支持的客户端库,而且二者也被包含在开发人员们使用的多种库及软件包之内。事实上,现在我们甚至已经很难找到一套不包含memcached或者redis内置支持机制的web堆栈。
  memcached与redis为什么如此受人拥戴?除了二者卓越的实际效果之外,双方各自极为简便的上手难度也是又一大加分项。无论是memcached还是redis,其使用便捷性在开发人员当中都可谓广为人知。只需要几分钟我们就能完成安装工作,并让它们开始与应用程序顺畅协作。换句话来说,只需投入一小部分时间与精力,大家就能获得立竿见影且效果极佳的性能表现提升――具体而言,性能将直接步入新的量级。面对如此简单而又能够带来巨大收益的解决方案,又有谁能抗拒得了它们的诱惑呢?
  何时应该使用memcached
  相对memcached而言,redis的面世时间更晚且具备更多功能,因此开发人员通常将其视为默认性首选方案。不过有两类特殊场景仍然是memcached的一家天下。首先就是对小型静态数据进行缓存处理,最具代表性的例子就是html代码片段。memcached的内部内存管理机制虽然不像redis的那样复杂,但却更具实际效率――这是因为memcached在处理元数据时所消耗的内存资源相对更少。作为memcached所支持的惟一一种数据类型,字符串非常适合用于保存那些只需要进行读取操作的数据,因为字符串本身无需进行进一步处理。
  除此之外,memcached在横向扩展方面也比redis更具优势。由于其在设计上的思路倾向以及相对更为简单的功能设置,memcached在实现扩展时的难度比redis低得多。不过根据我们了解到的情况,目前已经有多种经过测试且切实有效的方案能够将redis扩展至多台服务器之上,而其即将发布的3.0版本(感兴趣的朋友可以点击此处查看其候选版本说明)将包含专门针对横向扩展场景的内置集群化机制。
  何时应该使用redis
  除非大家需要考虑某种限定性条件(例如处理传统应用程序)对于memcached的特殊依赖性,或者自己的实际用例属于前面提到的两类场景中的一种,否则请直接选择redis并加以运用。凭借着redis所带来的卓越缓存方案,我们将拥有强大的处理能力――例如对缓存内容及持久性进行细节调整的能力――以及出色的整体执行效率。
  redis几乎在缓存管理工作中的每一个侧面都表现出显而易见的优越性。这套缓存方案采用所谓数据回收机制,能够将陈旧数据从内存中删除以提供新数据所必需的缓存空间。memcached的数据回收机制使用的是lru(即最低近期使用量)算法,而且往往会比较武断地直接删除掉与新数据体系相近的原有内容。相比之下,redis允许用户更为精准地进行细化控制,利用六种不同回收策略确切提高缓存资源的实际利用率。redis还采用更为复杂的内存管理与回收对象备选方案。
  redis还能为我们带来最大程度的灵活性空间,从而保证管理员在打理缓存对象时拥有充裕的施展平台。在这方面,memcached将键名限制在250字节,值也被限制在不超过1mb,且只适用于普通字符串。相比之下,redis则将键名与值的最大上限各自设定为512mb,且支持二进制格式。redis支持六种数据类型,因此能够更加智能地对数据进行缓存处理及操作,这相当于为应用程序开发人员敞开了一道通往无尽可能性的大门。
  相对于将对象保存为序列化字符串,redis允许开发人员以散列方式将对象域及值加以保存,并利用单一键对其进行管理。redis散列机制的存在保证开发人员无需经历获取完整字符串、反序列化、更新值、对象重新序列化并在每次值更新后利用其替代缓存内完整字符串这一系列复杂的流程――这也意味着资源消耗量得以降低、性能表现迎来显著提升。redis所支持的其它数据类型,例如lists以及sets――也可被用于实现更加复杂的缓存管理模式。
  redis的另一大重要优势在于,它所保存的数据具备透明化特性,也就是说服务器能够直接对这些数据进行操作。redis当中提供160多种可用命令,其中大部分用于实现数据处理操作并通过服务器端脚本将逻辑嵌入至数据存储体系当中。这些内置命令及用户脚本带来了极大的灵活性优势,足以帮助大家直接在redis内部完成数据处理任务――而不必将数据在网络中的其它专门处理系统之间来回移动。
  redis还提供可选而且能够具体调整的数据持久性方案,其设计目的在于在发生规划内停机或者计划外故障之后对缓存内容进行重新引导。虽然我们更倾向于强调缓存内数据的易失性与暂时性,但将数据在磁盘中加以持久保存在某些缓存场景当中仍然极具现实意义。这种机制能够在设备重启之后快速将保存在磁盘上的数据重新载入至缓存当中,从而大大缩短缓存预热周期并根据主数据存储内容对当前缓存内容进行重新评估。
  最后但也同样重要的一点是,redis能够提供复制功能。复制功能旨在帮助缓存体系实现高可用性配置方案,从而在遭遇故障的情况下继续为应用程序提供不间断的缓存服务。很明显,一套成熟的缓存方案应该能够在应用程序发生故障时略微甚至完全不给用户体验或者应用程序性能表现带来任何影响,而这种对缓存内容及服务可用性的有力保障在大多数情况下也成为缓存解决方案的一大主要优势。
  开源软件业界一直在不断努力,为我们带来当下技术领域中最为出色的各类解决方案。而在谈到利用缓存机制对应用程序性能表现加以提升这一话题时,redis与memcached作为两款广受赞誉而且久经考验的解决方案、也自然而然地成为完成这项任务的两大首选技术成果。不过从功能多样性以及设计先进性的角度出发,redis显然更适合被大家作为通用性的首选方案――除了少部分特殊场景之外。
关注小鸟云微信公众号

我要回帖

更多关于 mongodb 数据库备份 的文章

 

随机推荐