什么时候去Redis?什么时候到MongoDB?

时间:2011-03-23 02:23:47

标签: architecture mongodb nosql redis

我想要的不是Redis和MongoDB之间的比较。我知道他们是不同的;性能和API完全不同。

Redis非常快,但API非常'原子'。 MongoDB会占用更多资源,但API非常易于使用,我对它非常满意。

它们都非常棒,我想尽可能多地在部署中使用Redis,但是很难编码。我想尽可能多地在开发中使用MongoDB,但它需要一台昂贵的机器。

那么您如何看待它们的使用?什么时候选Redis?何时选择MongoDB?

10 个答案:

答案 0 :(得分:309)

我想说,这取决于您的开发团队类型以及您的应用程序需求。

例如,如果您需要大量查询,这通常意味着您的开发人员使用Redis会更加有效,您可以将数据存储在各种专用数据结构中,定制为了提高效率,每种类型的对象。在MongoDB中,相同的查询可能更容易,因为结构在整个数据中更加一致。另一方面,在Redis中,对这些查询的响应的纯粹的速度是处理数据可能存储的各种结构的额外工作的回报。

MongoDB为具有传统数据库和SQL体验的开发人员提供了简单,更短的学习曲线。但是,Redis的非传统方法需要更多的学习努力,但需要更大的灵活性。

EG。可以在Redis中更好地实现缓存层。对于更多可架构化的数据,MongoDB更好。 [注意:MongoDB和Redis在技术上都是无模式的]

如果你问我,我个人的选择是Redis满足大多数要求。

最后,我希望你现在看到http://antirez.com/post/MongoDB-and-Redis.html

答案 1 :(得分:236)

我刚才注意到这个问题很老了。不过,我认为值得补充以下几个方面:

  • 如果您还不知道如何查询数据,请使用MongoDB。

    MongoDB适用于黑客马拉松,初创公司或每次您不知道如何查询所插入的数据。 MongoDB不对您的底层架构做任何假设。虽然MongoDB是无模式和非关系的,但这并不意味着根本没有模式。它只是意味着您的架构需要在您的应用中定义(例如使用Mongoose)。除此之外,MongoDB非常适合原型设计或尝试。它的性能不是很好,也无法与Redis相提并论。

  • 使用Redis加速现有应用程序。

    Redis可以轻松集成为LRU cache。将Redis用作独立的数据库系统是非常罕见的(有些人更喜欢将其称为“键值”-store)。像Craigslist这样的网站使用Redis next to their primary database。 Antirez(Redis的开发人员)使用Lamernews证明了确实可以将Redis用作独立的数据库系统。

  • Redis不会根据您的数据做出任何假设。

    Redis提供了许多有用的数据结构(例如集合,散列,列表),但您必须明确定义如何存储数据。简而言之,可以使用Redis和MongoDB来实现类似的功能。 Redis速度更快,但不适合原型设计。这是一个通常更喜欢MongoDB的用例。除此之外,Redis 非常灵活。它提供的底层数据结构是高性能数据库系统的构建块。

何时使用Redis?

  • 缓存

    使用MongoDB进行缓存并不是很有意义。这太慢了。

  • 如果您有足够的时间考虑数据库设计。

    您不能简单地将文档输入Redis。您必须考虑要存储和组织数据的方式。一个例子是Redis中的哈希。它们与“传统的”嵌套对象完全不同,这意味着您必须重新考虑存储嵌套文档的方式。一种解决方案是将散列内的引用存储到另一个散列(类似 key:[id of second hash] )。另一个想法是将它存储为JSON,这对于具有* SQL背景的大多数人来说似乎是违反直觉的。

  • 如果您需要真正高性能。

    击败Redis提供的性能几乎是不可能的。想象一下,您的数据库与缓存一样快。这就是将Redis用作真正的数据库的感觉。

  • 如果你不关心 那么关于缩放。

    缩放Redis并不像以前那么难。例如,您可以使用一种代理服务器,以便在多个Redis实例之间分发数据。主从复制不是 复杂,但是在多个Redis实例之间分配密钥需要在应用程序站点上完成(例如使用哈希函数,Modulo等)。通过比较缩放MongoDB要简单得多。

何时使用MongoDB

  • Prototyping,Startups,Hackathons

    MongoDB非常适合快速原型设计。尽管如此,表现还不是那么好。另请注意,您很可能必须在应用程序中定义某种模式。

  • 当您需要快速更改架构时。

    因为没有架构!在传统的关系DBMS中更改表格非常昂贵且速度慢。 MongoDB通过不对您的基础数据做出很多假设来解决这个问题。尽管如此,它还是尽可能地优化,而不需要您定义架构。

<强> TL; DR - 如果性能很重要并且您愿意花时间优化和组织数据,请使用Redis。 - 如果您需要构建原型而不必过多担心数据库,请使用MongoDB。

进一步阅读:

答案 2 :(得分:223)

Redis的。假设您已经在php中编写了一个站点;无论出于什么原因,它变得流行,它超前于它的时间或者有色情内容。你意识到这个php太慢了,#34;我会失去我的粉丝,因为他们根本不会等待一个页面10秒钟。&#34;你突然意识到一个网页有一个常量的网址(它永远不会改变,哇),如果你愿意的话,它是一个主键,然后你会想起内存很快,而磁盘很慢而且php甚至更慢。 :(然后你使用内存和这个你称为&#34;键&#34的URL来设计存储机制;而你决定调用&#34;值的网页内容。&#34;这就是你所拥有的 - 关键你称它为#me; meme cache。&#34;你喜欢理查德道金斯,因为他很棒。你缓存你的html像松鼠一样缓存他们的坚果。你不需要重写你的垃圾PHP代码你很高兴。然后你看到其他人已经做到了 - 但是你选择了Redis,因为另一个有猫的混乱图像,有些还有f牙。

蒙戈。你写过一个网站。哎呀你写了很多,用任何语言写的。你意识到你花了很多时间来编写那些臭臭的SQL子句。你不是dba,但是你在那里,编写愚蠢的sql语句......不仅仅是一个,而是在各处吓坏。 &#34;选择此项,选择&#34;。但特别要记住烦人的WHERE子句。 lastname等于&#34; thornton&#34;和电影等于“坏圣诞老人。”#34; Urgh。你认为,&#34;为什么那些dbas不做他们的工作并给我一些存储过程?&#34;然后你忘记了一些像midname那样的小字段,然后你必须放弃表格,导出所有10G的大数据并用这个新字段创建另一个,然后输入数据 - 在接下来的14天里,你将继续10次继续记住像称呼,标题的废话,再加上带地址的外键。然后你认为lastname应该是lastName。每天几乎换一次。然后你说darnit。我必须继续写一个网站/系统,不要介意这个数据模型。所以你google,&#34;我讨厌编写SQL,请不要SQL,让它停止&#34;但流行音乐&#39; nosql&#39;然后你读了一些东西,它说它只是转储没有任何架构的数据。你记得上周惨败的桌子和笑容。然后你选择mongo因为一些大家伙喜欢&#39; airbud&#39; apt租赁网站使用它。甜。没有更多的数据模型更改,因为您有一个模型,您只是不断变化。

答案 3 :(得分:16)

也许这个资源有助于在两者之间做出决定。 它还讨论了其他几个NoSQL数据库,并提供了一个简短的特性列表,以及每个数据库的“我将用它来做什么”的解释。

http://kkovacs.eu/cassandra-vs-mongodb-vs-couchdb-vs-redis

答案 4 :(得分:11)

难以回答的问题 - 与大多数技术解决方案一样,它实际上取决于您的情况,因为您没有描述您试图解决的问题,有谁能提出解决方案?

您需要对它们进行测试,以确定哪些内容满足您的需求。

据说,MongoDB不需要任何昂贵的硬件。与任何其他数据库解决方案一样,它可以更好地处理更多的CPU和内存,但肯定不是必需的 - 特别是对于早期开发目的。

答案 5 :(得分:10)

Redis是内存数据存储,可以将其状态保存到磁盘(以便在重新启动后启用恢复)。但是,作为内存数据存储意味着数据存储(在单个节点上)的大小不能超过系统上的总内存空间(物理RAM +交换空间)。实际上,由于Redis与系统上的许多其他进程共享该空间,并且如果它耗尽系统内存空间,它可能会被操作系统杀死,这将远不如此。

Mongo是一个基于磁盘的数据存储,当它的工作集适合物理RAM(如所有软件)时效率最高。作为基于磁盘的数据意味着对Mongo数据库的大小没有内在限制,但是配置选项,可用磁盘空间和其他问题可能意味着超过某个限制的数据库大小可能变得不切实际或效率低下。

Redis和Mongo都可以进行群集,以实现高可用性,备份和增加数据存储的整体大小。

答案 6 :(得分:10)

所有答案(在撰写本文时)都假设Redis,MongoDB和基于SQL的关系数据库中的每一个都是基本相同的工具:&#34;存储数据&#34;。他们根本不考虑数据模型。

MongoDB:复杂数据

MongoDB是一个文档存储。与SQL驱动的关系数据库进行比较:关系数据库简化了索引的CSV文件,每个文件都是一个表;文档存储简化为索引的JSON文件,每个文件都是文档,多个文件组合在一起。

JSON文件在结构上类似于XML和YAML文件,与Python中的字典类似,因此请考虑这种层次结构中的数据。索引时,结构是关键:文档包含命名键,其中包含更多文档,数组或标量值。请考虑以下文档。

{
  _id:  0x194f38dc491a,
  Name:  "John Smith",
  PhoneNumber:
    Home: "555 999-1234",
    Work: "555 999-9876",
    Mobile: "555 634-5789"
  Accounts:
    - "379-1111"
    - "379-2574"
    - "414-6731"
}

上述文档的密钥为PhoneNumber.Mobile,其值为555 634-5789。您可以搜索密钥PhoneNumber.Mobile具有某些值的文档集合;他们被编入索引。

它还有一个包含多个索引的Accounts数组。可以查询Accounts包含完全某些值的子集,所有某些值的子集,或任何的文档>某些值的子集。这意味着您可以搜索Accounts = ["379-1111", "379-2574"]但找不到上述内容;您可以搜索Accounts includes ["379-1111"]并找到上述文件;并且您可以搜索Accounts includes any of ["974-3785","414-6731"]并查找上述内容以及包含帐户&#34; 974-3785&#34;的任何文件,如果有的话。

文档尽可能深入。 PhoneNumber.Mobile可以包含数组,甚至是子文档(PhoneNumber.Mobile.WorkPhoneNumber.Mobile.Personal)。如果您的数据是高度结构化的,那么文档就是关系数据库中的一大步。

如果您的数据大部分是平坦的,关系型的,结构严谨的,那么您最好使用关系数据库。同样,最重要的是,您的数据模型是否最适合于相关的CSV文件集合或XML / JSON / YAML文件集合。

对于大多数项目,您必须妥协,在SQL或文档商店不适合的某些小区域接受小规模的解决方案;对于存储大量数据的大型复杂项目(许多列;行无关紧要),将一些数据存储在一个模型中以及将其他数据存储在另一个模型中是有意义的。 Facebook使用SQL和图形数据库(数据放入节点,节点连接到其他节点); Craigslist曾经使用MySQL和MongoDB,但一直在考虑完全转移到MongoDB上。如果放在一个模型下,这些地方的数据跨度和关系将面临重大障碍。

Redis:键值

Redis最基本上是一个键值存储。 Redis允许您为其提供密钥并查找单个值。 Redis本身可以存储字符串,列表,哈希和其他一些东西;但是,它只是按名称查找。

缓存失效是计算机科学的难题之一;另一个是命名事物。这意味着当您想要避免数百个过多的后端查找时,您将使用Redis,但是您必须弄清楚何时需要新的查找。

最明显的失效案例是写时更新:如果您阅读user:Simon:lingots = NOTFOUND,则可以SELECT Lingots FROM Store s INNER JOIN UserProfile u ON s.UserID = u.UserID WHERE u.Username = Simon并将结果100存储为SET user:Simon:lingots = 100。然后,当您授予Simon 5 lingots时,您会看到user:Simon:lingots = 100SET user:Simon:lingots = 105UPDATE Store s INNER JOIN UserProfile u ON s.UserID = u.UserID SET s.Lingots = 105 WHERE u.Username = Simon。现在你的数据库和Redis中有105个,并且可以在不查询数据库的情况下获得user:Simon:lingots

第二种情况是更新相关信息。我们假设你生成一个页面块并缓存它们的输出。标题显示了玩家的经验,水平和金额;玩家的个人资料页面有一个显示其统计信息的块;等等。玩家获得一些经验。好了,现在您有几个templates:Header:Simontemplates:StatsBox:Simontemplates:GrowthGraph:Simon等字段,您已经缓存了通过模板引擎运行的六个数据库查询的输出。通常,当您显示这些页面时,您会说:

$t = GetStringFromRedis("templates:StatsBox:" + $playerName);
if ($t == null) {
  $t = BuildTemplate("StatsBox.tmpl",
                     GetStatsFromDatabase($playerName));
  SetStringInRedis("Templates:StatsBox:" + $playerName, $t);
}
print $t;

由于您刚刚更新了GetStatsFromDatabase("Simon")的结果,因此您必须将templates:*:Simon从密钥值缓存中删除。当您尝试渲染任何这些模板时,您的应用程序将从数据库(PostgreSQL,MongoDB)中提取数据并将其插入模板中;然后它会将结果存储在Redis中,并且希望在下次显示该输出块时不会费心进行数据库查询和渲染模板。

Redis还允许您执行发布者订阅消息队列等。这完全是另一个话题。这里指的是Redis是一个键值缓存,它与关系数据库或文档存储区别不同。

结论

根据您的需求选择工具。最大的需求通常是数据模型,因为它决定了代码的复杂性和容易出错的程度。专业应用程序将依赖于性能,您可以在C和Assembly的混合中编写所有内容;大多数应用程序只处理通用情况并使用一个缓存系统,如Redis或Memcached,这比高性能SQL数据库或文档存储快得多。

答案 7 :(得分:2)

如果你有足够的RAM,你也不应该使用它。 Redis和MongoDB是以通用工具为代价的。这引入了很多开销。

有人说Redis比Mongo快10倍。那可能不再那么真实了。只要内存配置相同,MongoDB(如果我没记错的话)声称可以通过内存和缓存文件来打败memcache。

总之。 Redis很好,MongoDB很好。如果您关心子结构并需要聚合,请访问MongoDB。如果存储密钥和值是您主要关心的全部关于Redis。 (或任何其他键值存储)。

答案 8 :(得分:2)

Redis和MongoDB都是非关系数据库,但它们属于不同的类别。

Redis是一个Key / Value数据库,它使用内存存储,使其超快。它是缓存和临时数据存储(在内存中)的理想选择,并且由于大多数云平台(例如Azure,AWS)支持它,它的内存使用是可扩展的。但是如果你要在你的机器上使用它有限的资源,考虑它的内存使用情况。

另一方面,MongoDB是一个文档数据库。这是保存大型文本,图像,视频等以及除了交易之外的数据库所做的几乎任何事情的好选择。例如,如果您想开发博客或社交网络,MongoDB是一个合适的选择。它具有横向扩展策略的可扩展性。它使用磁盘作为存储介质,因此数据将被保留。

答案 9 :(得分:1)

如果你的项目已经让你的环境有足够的RAM内存 - 那就是Redis。特别是考虑到具有集群功能的新Redis 3.2。