Answers:
我要说的是,这取决于您是什么样的开发团队以及您的应用程序需求。
例如,如果您需要进行大量查询,那么大多数情况下,这意味着开发人员使用Redis可能需要做更多工作,因为您的数据可能存储在各种专门的数据结构中,这些结构针对每种类型的对象进行了自定义以提高效率。在MongoDB中,相同的查询可能会更容易,因为整个数据的结构更加一致。另一方面,在Redis中,对这些查询的快速响应是处理数据可能存储的各种结构的额外工作的回报。
MongoDB为具有传统DB和SQL经验的开发人员提供了简单,短得多的学习曲线。但是,Redis的非传统方法需要付出更多的努力来学习,但需要更大的灵活性。
例如。一个缓存层很可能在Redis的得到更好的执行。对于更多可用于模式的数据,MongoDB更好。 [注意:MongoDB和Redis在技术上都是无模式的]
如果您问我,对于大多数要求,我的个人选择是Redis。
最后,我希望到目前为止您已经看过http://antirez.com/post/MongoDB-and-Redis.html
我只是注意到这个问题已经很老了。不过,我认为以下几个方面值得补充:
如果您还不知道如何查询数据,请使用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 确实非常灵活。它提供的基础数据结构是高性能数据库系统的构建块。
快取
使用MongoDB进行缓存根本没有多大意义。太慢了。
如果您有足够的时间考虑数据库的设计。
您不能简单地将文档放入Redis。您必须考虑存储和组织数据的方式。一个例子是Redis中的哈希。它们与“传统的”嵌套对象完全不同,这意味着您必须重新考虑存储嵌套文档的方式。一种解决方案是将散列内的引用存储到另一个散列(类似于键:[第二个散列的ID])。另一个想法是将其存储为JSON,对于大多数具有* SQL背景的人来说,这似乎是违反直觉的。
如果您需要真正的高性能。
击败Redis提供的性能几乎是不可能的。想象一下您的数据库与缓存一样快。这就是使用Redis作为真实数据库的感觉。
如果你不小心说太多关于缩放。
扩展Redis并不像以前那样困难。例如,您可以使用一种代理服务器来在多个Redis实例之间分发数据。主从复制并不那么复杂,但是需要在应用程序站点上完成在多个Redis实例之间分配密钥的工作(例如,使用哈希函数,Modulo等)。相比之下,对MongoDB进行扩展要简单得多。
原型设计,初创公司,黑客马拉松
MongoDB非常适合快速原型制作。但是,性能并不是那么好。还要记住,您很可能必须在应用程序中定义某种模式。
当您需要快速更改架构时。
因为没有架构!在传统的关系型DBMS中更改表非常昂贵且缓慢。MongoDB通过不对基础数据进行大量假设来解决此问题。但是,它尝试在不要求定义架构的情况下尽可能地进行优化。
TL; DR- 如果性能很重要,并且愿意花时间优化和组织数据,请使用Redis。-如果您需要构建原型而不必担心数据库过多,请使用MongoDB。
进一步阅读:
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存储如何解决此问题?:)
也许此资源很有用,有助于在两者之间做出决定。它还讨论了其他几个NoSQL数据库,并提供了简短的特性列表,并为每个特性提供了“我将用它做什么”的说明。
很难回答的问题-与大多数技术解决方案一样,这实际上取决于您的情况,并且由于您没有描述要解决的问题,因此有人可以提出解决方案吗?
您需要对它们进行测试,以查看其中哪一个满足您的需求。
话虽如此,MongoDB不需要任何昂贵的硬件。像任何其他数据库解决方案一样,它将在更多的CPU和内存上更好地工作,但是当然不是必需的-尤其是对于早期开发目的。
Redis是内存中的数据存储,可以将其状态持久保存到磁盘(以在重新启动后进行恢复)。但是,作为内存中数据存储区意味着数据存储区(在单个节点上)的大小不能超过系统上的总存储空间(物理RAM +交换空间)。实际上,这要少得多,因为Redis正在与系统上的许多其他进程共享该空间,并且如果它耗尽了系统内存空间,很可能会被操作系统杀死。
Mongo是基于磁盘的数据存储,当它的工作集适合物理RAM(如所有软件)时,效率最高。作为基于磁盘的数据,意味着Mongo数据库的大小没有内在的限制,但是配置选项,可用磁盘空间和其他问题可能意味着超过一定限制的数据库大小可能变得不切实际或效率低下。
Redis和Mongo都可以集群化,以实现高可用性,备份并增加数据存储的整体大小。
所有的答案(在撰写本文时)都假设Redis,MongoDB以及可能基于SQL的关系数据库中的每一个实质上都是相同的工具:“存储数据”。他们根本不考虑数据模型。
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.Work
和PhoneNumber.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个lingots,你看user:Simon:lingots = 100
,SET user:Simon:lingots = 105
和UPDATE 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:Simon
,templates:StatsBox:Simon
,templates: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数据库或文档存储要快得多。