关于建筑:什么时候去Redis? 什么时候到MongoDB?

When to Redis? When to MongoDB?

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

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

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

那么你怎么看待它们的使用呢? 什么时候选Redis? 什么时候选择MongoDB?


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

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

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

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

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

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


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

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

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

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

    Redis可以轻松集成为LRU缓存。将Redis用作独立的数据库系统是非常罕见的(有些人更喜欢将其称为"键值"-store)。像Craigslist这样的网站在他们的主数据库旁边使用Redis。 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

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

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

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

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

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

进一步阅读:

  • 将Redis用作主数据存储时要考虑的有趣方面


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

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


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

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


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

您需要测试它们以查看哪些满足您的需求。

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


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

MongoDB:复杂数据

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

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

1
2
3
4
5
6
7
8
9
10
11
12
{
  _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或文档存储不适合的一些小区域中进行小规模的解决方案;对于存储大量数据的大型复杂项目(许多列;行无关紧要),将一些数据存储在一个模型中以及将其他数据存储在另一个模型中是有意义的。 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等字段,你已经缓存了通过模板引擎运行的六个数据库查询的输出。通常,当您显示这些页面时,您会说:

1
2
3
4
5
6
7
$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数据库或文档存储快得多。

好。


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

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

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


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

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

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


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

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

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


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