什么时候去Redis?什么时候使用MongoDB?

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

Redis非常快,但是API非常“原子化”。MongoDB会消耗更多的资源,但是API非常非常容易使用,我对它非常满意。

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

那么你认为两者的作用是什么呢?什么时候选择Redis?什么时候选择MongoDB?

323224 次浏览

很难回答的问题——和大多数技术解决方案一样,这真的取决于你的情况,因为你没有描述你正在试图解决的问题,谁能提出解决方案呢?

你需要测试它们两个,看看哪一个满足你的需求。

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

我想说的是,这取决于你所在的开发团队以及你的应用程序需求。

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

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

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

如果你问我,我个人对大多数需求的选择是Redis。

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

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

< a href = " http://kkovacs。欧盟/ cassandra-vs-mongodb-vs-couchdb-vs-redis noreferrer“rel = > http://kkovacs.eu/cassandra-vs-mongodb-vs-couchdb-vs-redis < / >

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

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

    MongoDB适用于黑客马拉松,创业公司或每次你不知道如何查询你插入的数据。MongoDB不会对底层模式做任何假设。虽然MongoDB是无模式且非关系型的,但这并不意味着根本就没有模式。这仅仅意味着你的模式需要在你的应用程序中定义(例如使用Mongoose)。除此之外,MongoDB非常适合创建原型或进行尝试。它的性能不是很好,不能和Redis相比

  • 使用Redis是为了加快你现有的应用程序。

    Redis可以很容易地集成为LRU缓存。将Redis作为一个独立的数据库系统使用是非常少见的(有些人更喜欢将其称为“键-值”存储)。像Craigslist这样的网站使用Redis紧挨着他们的主数据库。Antirez (Redis的开发者)使用Lamernews演示了确实可以将Redis作为一个独立的数据库系统使用

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

    Redis提供了一堆有用的数据结构(例如集,哈希,列表),但你必须显式地定义你想要如何存储你的数据。简而言之,Redis和MongoDB可以用来实现类似的事情。Redis速度更快,但不适合做原型。这是一个您通常更喜欢MongoDB的用例。除此之外,Redis是真的灵活的。它提供的底层数据结构是高性能数据库系统的构建块

什么时候使用Redis?

  • < p >缓存

    使用MongoDB进行缓存没有太大意义。

  • 如果你有足够的时间考虑你的DB设计。

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

  • 如果你需要真的高性能。

    要打败Redis提供的性能几乎是不可能的。假设你的数据库和你的缓存一样快。这就是使用Redis作为真正的数据库的感觉

  • 如果你不太关心缩放。

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

何时使用MongoDB

  • 原型,创业,黑客松

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

  • 当你需要快速改变你的模式。

    因为没有图式!在传统的关系DBMS中修改表既昂贵又缓慢。MongoDB通过不对底层数据做大量假设来解决这个问题。不过,它会在不要求您定义模式的情况下尽可能地进行优化

< >强TL,博士 -如果性能是重要的,你愿意花时间优化和组织你的数据使用Redis。 -如果你需要构建一个原型,可以使用MongoDB,而不用太担心你的DB

进一步阅读:

复述。假设你用php写了一个网站;不管出于什么原因,它变得流行起来,它领先于它的时代,或者上面有色情内容。你意识到这个php非常慢,“我将失去我的粉丝,因为他们根本不会为一个页面等待10秒钟。”你突然意识到一个网页有一个固定的url(它永远不会改变,哇),如果你愿意的话,一个主键,然后你想起内存很快,而磁盘很慢,php甚至更慢。(然后你使用内存和这个URL(你称之为“键”)构建一个存储机制,而你决定将网页内容称为“值”。这就是你所拥有的——密钥和内容。你称之为“模因缓存”。你喜欢理查德·道金斯,因为他很棒。你缓存html就像松鼠缓存坚果一样。你不需要重写你的php代码。你是快乐的。然后你看到其他人也这么做了——但你选择了Redis,因为另一个网站上有令人困惑的猫的图片,有些还长着尖牙。

蒙戈。你写了一个网站。见鬼,你写了很多,而且是用任何语言写的。您意识到您的大部分时间都花在编写那些讨厌的SQL子句上了。你不是dba,但你却在写愚蠢的sql语句……不只是一个,到处都是。“选择这个,选择那个”。但你一定记得那个恼人的WHERE从句。姓氏等于桑顿电影等于坏圣诞老人呃!。你会想,“为什么那些dba不做他们的工作,给我一些存储过程呢?”然后您忘记了一些次要字段,如middleame,然后您必须删除表,导出所有10G的大数据,并使用这个新字段创建另一个大数据,然后导入数据——在接下来的14天内重复10次,因为您一直在记住诸如称呼、标题以及添加带有地址的外键之类的垃圾。然后你认为lastname应该是lastname。几乎一天换一次。然后你说该死。我必须开始写一个网站/系统,更不用说这个数据模型了。所以你谷歌,“我讨厌写SQL,请不要写SQL,让它停止”,但弹出“nosql”,然后你读到一些东西,它说它只是转储数据,没有任何模式。你还记得上周丢了更多桌子的惨败,微笑吧。然后你选择mongo,因为一些大的家伙喜欢“airbud”,apt租赁网站使用它。甜的。没有更多的数据模型变化,因为你有一个模型,你只是不断地改变。

如果你有足够的RAM,你应该使用这两种方法。Redis和MongoDB达到了通用工具的价格。这会带来很多开销。

有一种说法是Redis比Mongo快10倍。这可能不再是真的了。MongoDB(如果我没记错的话)声称只要内存配置相同,就可以在存储和缓存文档方面击败memcache。

不管怎样。Redis不错,MongoDB也不错。如果你关心子结构并且需要聚合,那么就选择MongoDB。如果存储键和值是你主要关心的,它都是关于Redis。(或任何其他键值存储)。

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

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

Redis和Mongo都可以通过集群来实现高可用性、备份和增加数据存储的整体大小。

所有的答案(在撰写本文时)都假设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,其值为555 634-5789。你可以在键PhoneNumber.Mobile有值的文档集合中搜索;他们的索引。

它还有一个包含多个索引的Accounts数组。可以查询一个文档,其中Accounts包含完全某个值子集,所有某个值子集,或任何某个值子集。这意味着你可以搜索Accounts = ["379-1111", "379-2574"]而找不到上面的;你可以搜索Accounts includes ["379-1111"]并找到上面的文档;你可以搜索Accounts includes any of ["974-3785","414-6731"],找到上面和任何包含帐户“974-3785”的文档(如果有的话)。

你想要多深就有多深。PhoneNumber.Mobile可以保存一个数组,甚至一个子文档(PhoneNumber.Mobile.WorkPhoneNumber.Mobile.Personal)。如果您的数据是高度结构化的,文档是关系数据库的一大进步。

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

对于大多数项目,您将不得不妥协,在SQL或Document store不适合的一些小领域接受一些小的变通方法;对于一些存储广泛数据(许多列;行是不相关的),将一些数据存储在一个模型中,另一些数据存储在另一个模型中是有意义的。Facebook同时使用SQL和图形数据库(数据被放入节点中,节点与其他节点连接);Craigslist曾经使用MySQL和MongoDB,但一直在考虑完全转移到MongoDB。在这些地方,如果把数据的跨度和关系放在一个模型下,就会面临重大障碍。

复述:键值

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。然后当你奖励西蒙5个灵格时,你会读到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数据库或文档存储要快得多。

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

Redis是一个键/值数据库,它使用内存存储,这使得它非常快。它是缓存和临时数据存储(在内存中)的一个很好的候选人,因为大多数云平台(如Azure,AWS)都支持它,它的内存使用是可扩展的。但是如果您要在资源有限的机器上使用它,请考虑它的内存使用量。

另一方面,MongoDB是一个文档数据库。对于保存大型文本、图像、视频等以及几乎所有与数据库相关的内容(除了事务)来说,这是一个很好的选择。例如,如果你想开发一个博客或社交网络,MongoDB是一个合适的选择。它具有向外扩展的策略。它使用磁盘作为存储介质,因此数据将被持久化。

如果你的项目预算允许你有足够的RAM内存在你的环境-答案是Redis。尤其是考虑到新的Redis 3.2的集群功能。