什么时候去Redis?什么时候去MongoDB?[关闭]


466

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

Redis的速度非常快,但API的“原子性”非常好。MongoDB将占用更多资源,但是该API非常易于使用,对此我感到非常满意。

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

那么您如何看待两者的使用呢?何时选择Redis?何时选择MongoDB?

Answers:


308

我要说的是,这取决于您是什么样的开发团队以及您的应用程序需求。

例如,如果您需要进行大量查询,那么大多数情况下,这意味着开发人员使用Redis可能需要做更多工作,因为您的数据可能存储在各种专门的数据结构中,这些结构针对每种类型的对象进行了自定义以提高效率。在MongoDB中,相同的查询可能会更容易,因为整个数据的结构更加一致。另一方面,在Redis中,对这些查询的快速响应是处理数据可能存储的各种结构的额外工作的回报。

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

例如。一个缓存层很可能在Redis的得到更好的执行。对于更多可用于模式的数据,MongoDB更好。 [注意:MongoDB和Redis在技术上都是无模式的]

如果您问我,对于大多数要求,我的个人选择是Redis。

最后,我希望到目前为止您已经看过http://antirez.com/post/MongoDB-and-Redis.html


16
仅供参考,mongodb是无模式的。
Özgür的

18
MogoDB是无模式的。随着数据库中存储的数据越来越大,MongoDB证明它比Redis快得多。仅当存储的数据较小时,Redis才更快。
安徒生

4
我喜欢MongoDB的无模式方法,然后让ORM作者为需要它们的人实现模式。猫鼬是一个很棒的ORM,如果需要,它会引入易于使用的模式:)
Chev 2014年

18
您应该知道,redis数据库的大小受计算机中RAM数量的限制。任何大于此的值,您都必须考虑手动且密集的群集。
Akash Agrawal,2014年

4
MongoDB没有强制执行架构,但是我想看看有人在没有架构的情况下使用它的情况……这就是定义“架构”一词的全部方式
Robbie Guilfoyle 2014年

236

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

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

    MongoDB适用于Hackathon,初创企业或每次您不知道如何查询插入的数据时。MongoDB对您的基础架构不做任何假设。尽管MongoDB是无架构且非关系的,但这并不意味着根本没有架构。这只是意味着您的架构需要在您的应用程序中定义(例如,使用Mongoose)。除此之外,MongoDB非常适合原型设计或尝试。它的性能不是那么好,无法与Redis相提并论。

  • 使用Redis可以加快现有应用程序的速度。

    Redis可以很容易地集成为LRU缓存。将Redis用作独立的数据库系统非常罕见(有些人更喜欢将其称为“键值”存储)。诸如Craigslist之类的网站在其主数据库旁边使用Redis。Antirez(Redis的开发人员)使用Lamernews演示了确实有可能将Redis用作独立的数据库系统。

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

    Redis提供了一堆有用的数据结构(例如,集合,哈希,列表),但您必须明确定义要如何存储数据。简而言之,可以使用Redis和MongoDB来实现类似的目的。Redis速度更快,但不适合原型制作。那是一个您通常会喜欢MongoDB的用例。除此之外,Redis 确实非常灵活。它提供的基础数据结构是高性能数据库系统的构建块。

什么时候使用Redis?

  • 快取

    使用MongoDB进行缓存根本没有多大意义。太慢了。

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

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

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

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

  • 如果你不小心太多关于缩放。

    扩展Redis并不像以前那样困难。例如,您可以使用一种代理服务器来在多个Redis实例之间分发数据。主从复制并不那么复杂,但是需要在应用程序站点上完成在多个Redis实例之间分配密钥的工作(例如,使用哈希函数,Modulo等)。相比之下,对MongoDB进行扩展要简单得多。

何时使用MongoDB

  • 原型设计,初创公司,黑客马拉松

    MongoDB非常适合快速原型制作。但是,性能并不是那么好。还要记住,您很可能必须在应用程序中定义某种模式。

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

    因为没有架构!在传统的关系型DBMS中更改表非常昂贵且缓慢。MongoDB通过不对基础数据进行大量假设来解决此问题。但是,它尝试在不要求定义架构的情况下尽可能地进行优化。

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

进一步阅读:


3
如果您有足够的时间考虑数据库的设计。要实现它:假设您要存储SO数据。 在Mongo中:只需转储带有嵌套答案和注释的完整问题,但是在redis中,您必须执行以下操作:SO on redis
Abhishek Gupta

223

Redis。假设您已经用php编写了一个网站;无论出于何种原因,它都变得流行,并且它已经过时或带有色情内容。您意识到这个php太慢了,“我会失去我的粉丝的,因为他们根本不会等10秒才能看到页面。” 您突然意识到一个网页具有恒定的url(它永远不会改变,哇),如果愿意的话,它是一个主键,然后您回想起内存快而磁盘慢而php慢。:(然后,您使用内存和此URL来构造存储机制,并在您决定将网页内容称为“值”的同时将其称为“键”。这就是您所拥有的全部-键和内容。您将其称为“ meme缓存”。您喜欢Richard Dawkins,因为他很棒。您可以像松鼠一样缓存html来缓存它们的螺母,而无需重写废话php代码。你很快乐。然后,您会看到其他人也这样做了-但您选择Redis是因为另一人的猫的图像令人困惑,有些带有毒牙。

蒙哥 您已经写了一个网站。哎呀,您用任何语言都写过很多东西。您意识到自己的大部分时间都花在编写那些令人讨厌的SQL子句上。您不是dba,但您在那里,正在编写愚蠢的sql语句……不仅是一个,而且到处都是。“选择这个,选择那个”。但尤其要记住令人讨厌的WHERE子句。电影的姓氏等于“ thornton”,电影等于“坏圣诞老人”。嗯 您认为,“为什么那些dbas不能只做他们的工作并给我一些存储过程?” 然后您忘记了一些中间字段,例如“中间名”,然后必须删除表,导出所有10G大数据,并使用此新字段创建另一个,然后导入数据-在接下来的14天中,此过程将持续10次继续记住废话,如称呼,头衔,加上带有地址的外键。然后,您确定姓氏应为lastName。每天差不多要换一次。然后你说达尼特。我必须继续并编写一个网站/系统,不用管这个数据模型bs。因此,您用谷歌搜索“我讨厌编写SQL,请不要使用SQL,请使其停止”,但是弹出“ nosql”,然后您读到一些内容,并说它只是在不使用任何模式的情况下转储数据。您还记得上周惨败的时候,他们摆出了更多的桌子和微笑。然后,您选择mongo,因为像“ airbud”之类的大人物在合适的租赁网站上使用了它。甜。无需更改任何数据模型,因为您拥有不断更改的模型。


您是什么意思You don't need to rewrite your crap php code?,kv存储如何解决此问题?:)
罗伊·李

13
@Roylee他的意思是缓慢而and脚的php输出html网页。无需费心地重写代码以使其更快/更高效,您只需在开始时运行一次php,然后永远运行一次,只需使用您的kv商店调用html中的预建网页即可。
Mikepote '16

您讲这个故事的方式帮助我最终概念化了为什么无模式的超赞!刚刚为我节省了不得不使用SQL来了解功能的几年时间。
尼克·皮内达

4
“不再更改模型”并不能真正抓住情况。除非您编写数据运动代码来更新所有现有条目,否则就更像您有“ N”个略有不同的模型同时都存在于同一数据库中,并且您的代码必须确定何时处理哪个模型。它从数据库读取某些内容。
特里·科塔

2
我见过的绝对最佳答案之一。它具有丰富的内容,实际上使我大声笑出来(字面上不是笑)
colbyJax


11

很难回答的问题-与大多数技术解决方案一样,这实际上取决于您的情况,并且由于您没有描述要解决的问题,因此有人可以提出解决方案吗?

您需要对它们进行测试,以查看其中哪一个满足您的需求。

话虽如此,MongoDB不需要任何昂贵的硬件。像任何其他数据库解决方案一样,它将在更多的CPU和内存上更好地工作,但是当然不是必需的-尤其是对于早期开发目的。


10

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

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

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


10

所有的答案(在撰写本文时)都假设Redis,MongoDB以及可能基于SQL的关系数据库中的每一个实质上都是相同的工具:“存储数据”。他们根本不考虑数据模型。

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,它具有value 555 634-5789。您可以搜索文档集合,其中的关键字,,键PhoneNumber.Mobile具有一定的价值;他们被索引。

它还具有一个包含Accounts多个索引的数组。可以查询其中恰好Accounts包含一些值子集,所有值子集或任何值子集的文档。这意味着您可以搜索而不是上面的内容;您可以搜索并找到上述文档;并且您可以搜索并找到以上内容以及包含帐户“ 974-3785”的任何文档(如果有)。Accounts = ["379-1111", "379-2574"]Accounts includes ["379-1111"]Accounts includes any of ["974-3785","414-6731"]

文件可以随心所欲。 PhoneNumber.Mobile可能包含一个数组,甚至一个子文档(PhoneNumber.Mobile.WorkPhoneNumber.Mobile.Personal)。如果您的数据是高度结构化的,则文档比关系数据库要大得多。

如果您的数据大多是平坦的,关系的和严格的结构,那么最好使用关系数据库。同样,最大的标志是您的数据模型是最适合于相互关联的CSV文件集合还是XML / JSON / YAML文件集合。

对于大多数项目,您将不得不妥协,在SQL或Document Store都不适合的一些小区域接受较小的解决方法。对于一些存储大量数据的大型复杂项目(许多列;行无关),将一些数据存储在一个模型中而将其他数据存储在另一个模型中是有意义的。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结果存储100SET user:Simon:lingots = 100。然后,当你奖励西蒙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语言和汇编语言混合编写所有内容。大多数应用程序只会处理一般情况,并使用缓存系统(例如Redis或Memcached),这比高性能SQL数据库或文档存储要快得多。


2
“缓存失效是计算机科学的难题之一;另一个是命名问题。” 如此真实!
2016年

2

如果您有足够的RAM,则不应该使用它们。Redis和MongoDB的价格是通用工具的价格。这引入了很多开销。

有人说Redis比Mongo快10倍。那可能不再是真的了。只要内存配置相同,MongoDB(如果我没记错的话)声称击败了用于存储和缓存文档的memcache。

无论如何。Redis好,MongoDB好。如果您关心子结构并需要聚合,请使用MongoDB。如果存储键和值是您的主要关注点,则它与Redis有关。(或任何其他键值存储)。


2

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

Redis是一个键/值数据库,它使用的是内存中存储,这使其超快。它是在内存中缓存内容和临时数据的理想选择,并且由于大多数云平台(例如Azure,AWS)都支持它,因此它的内存使用量是可伸缩的。资源有限,请考虑它的内存使用情况。

另一方面,MongoDB是一个文档数据库。这是保留大型文本,图像,视频等几乎所有与事务有关的数据库的好选择,例如,如果您想开发博客或社交网络,MongoDB是一个合适的选择。可通过横向扩展策略进行扩展。它使用磁盘作为存储介质,因此数据将被保留。


1

如果您提出的项目允许您在环境中拥有足够的RAM内存-答案是Redis。尤其要考虑到具有集群功能的新Redis 3.2。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.