【问题标题】:When to Redis? When to MongoDB? [closed]何时使用 Redis?何时使用 MongoDB? [关闭]
【发布时间】:2011-07-20 23:40:39
【问题描述】:

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

Redis 非常快,但 API 非常“原子”。 MongoDB会吃更多资源,但是API非常非常好用,我很满意。

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

那么你觉得两者的使用如何?什么时候选择 Redis?什么时候选择 MongoDB?

【问题讨论】:

    标签: architecture mongodb nosql redis


    【解决方案1】:

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

    您需要同时测试它们,看看它们中的哪一个满足您的需求。

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

    【讨论】:

      【解决方案2】:

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

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

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

      例如。 cache 层可能在 Redis 中实现得更好。对于更多支持模式的数据,MongoDB 更好。 [注意:MongoDB 和 Redis 在技术上都是无模式的]

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

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

      【讨论】:

      • 仅供参考,mongodb 是无模式的。
      • MogoDB 是无模式的。并且随着存储在数据库中的数据越来越大,MongoDB 证明它比 Redis 快得多。 Redis 只有在存储的数据较小时才会更快。
      • 我喜欢 MongoDB 无模式的方法,然后让 ORM 作者为需要它们的人实现模式。 Mongoose 是一个很棒的 ORM,如果你需要它们,它会引入易于使用的模式 :)
      • 你应该知道redis数据库大小受机器内存大小的限制。任何比这更大的,你都必须考虑手动和密集的集群。
      • MongoDB 不强制使用模式,但我希望看到有人在没有模式的情况下使用它的情况......这就是你定义单词模式的方式
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

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

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

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

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

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

          Redis 提供了一堆有用的数据结构(例如 Sets、Hashes、Lists),但您必须明确定义要如何存储数据。简而言之,可以使用 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。

        进一步阅读:

        【讨论】:

        • 如果您有足够的时间来考虑您的数据库设计。 实现它:假设您要存储 SO 数据。 在 Mongo 中:只需使用嵌套答案和 cmets 转储完整的问题,但 在 redis 中您必须执行以下操作:SO on redis
        【解决方案5】:

        Redis。假设您已经用 php 编写了一个站点;无论出于何种原因,它变得流行并且领先于时代或带有色情内容。你意识到这个 php 太慢了,“我会失去我的粉丝,因为他们根本不会等待 10 秒来获得一个页面。”你突然意识到一个网页有一个固定的 url(它永远不会改变,哇),一个主键,如果你愿意的话,然后你回想起内存是快的,而磁盘是慢的,而 php 甚至更慢。 :( 然后你使用内存和这个 URL 设计一个存储机制,你称之为“键”,而网页内容你决定称之为“值”。这就是你所拥有的 - 键和内容。你称之为“模因缓存”。你喜欢 Richard Dawkins,因为他很棒。你缓存你的 html 就像松鼠缓存他们的坚果一样。你不需要重写你的垃圾 php 代码。你很高兴。然后你看到其他人已经做到了——但你选择 Redis 是因为另一个有猫的令人困惑的图像,有些带有尖牙。

        蒙古。你写了一个网站。哎呀,你写了很多,而且用任何语言。您意识到您的大部分时间都花在了编写那些臭名昭著的 SQL 子句上。你不是 dba,但你却在写愚蠢的 sql 语句……不只是一个,而且到处都吓坏了。 “选择这个,选择那个”。但特别是你记得恼人的 WHERE 子句。其中lastname 等于“thornton”,movie 等于“bad santa”。呃。你会想,“为什么那些 dbas 不做他们的工作,给我一些存储过程呢?”然后你忘记了一些像中间名这样的次要字段,然后你必须删除表,导出所有 10G 的大数据,并使用这个新字段创建另一个,然后导入数据——在接下来的 14 天内,这会持续 10 次。继续记住诸如称呼,标题之类的废话,以及添加带有地址的外键。然后你认为lastname 应该是lastName。几乎一天换一次。然后你说达尼特。我必须着手编写一个网站/系统,不要介意这个数据模型。所以你用谷歌搜索,“我讨厌写 SQL,请不要写 SQL,让它停下来”,但弹出“nosql”,然后你读了一些东西,它说它只是转储没有任何模式的数据。你记得上周的惨败丢下更多桌子和微笑。然后你选择了 mongo,因为一些像 'airbud' 这样的大人物在 apt 租赁网站上使用它。甜的。无需再更改数据模型,因为您有一个模型可以不断更改。

        【讨论】:

        • You don't need to rewrite your crap php code?是什么意思,k-v store是怎么解决这个问题的? :)
        • @Roylee 他的意思是缓慢而蹩脚的 php 以 html 输出网页。您无需费力地重写代码以使其更快/更高效,而是在开始时运行一次 php,然后永远运行,只需使用您的 k-v 商店调用 html 中的预构建网页。
        • 您讲述这个故事的方式帮助我最终概念化了为什么无模式很棒!只是为我节省了几年处理 SQL 以了解其强大功能的时间。
        • “不再更改模型”并不能真正捕捉到这种情况。除非您编写数据运动代码来更新所有现有条目,否则它更像是您有“N”个稍微不同的模型都同时存在于同一个数据库中,并且您的代码必须弄清楚它何时处理哪个模型它从数据库中读取一些东西。
        • 我见过的绝对最好的答案之一。它有很棒的内容,实际上让我大笑(字面意思不是大声笑)
        【解决方案6】:

        如果您有足够的 RAM,则两者都不应该使用。 Redis 和 MongoDB 达到了通用工具的价格。这会带来很多开销。

        有人说 Redis 比 Mongo 快 10 倍。这可能不再那么真实了。只要内存配置相同,MongoDB(如果我没记错的话)声称在存储和缓存文档方面胜过 memcache。

        无论如何。 Redis 好,MongoDB 好。如果您关心子结构并需要聚合,请选择 MongoDB。如果存储键和值是您的主要关注点,那么它就是 Redis。 (或任何其他键值存储)。

        【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

            【解决方案8】:

            所有答案(在撰写本文时)都假设 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 或文档存储不适合的一些小范围内接受较小的解决方法;对于一些存储广泛数据(许多列;行无关)的大型复杂项目,将一些数据存储在一个模型中并将其他数据存储在另一个模型中是有意义的。 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。然后,当您授予西蒙 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 数据库或文档存储快得多。

            【讨论】:

            • "缓存失效是计算机科学的难题之一;另一个是命名事物。"太真实了!
            【解决方案9】:

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

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

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

            【讨论】:

              【解决方案10】:

              如果您的项目预算允许您在环境中拥有足够的 RAM 内存 - 答案是 Redis。特别是考虑到具有集群功能的新 Redis 3.2。

              【讨论】:

                猜你喜欢
                • 2011-06-26
                • 2011-10-17
                • 1970-01-01
                • 2013-05-23
                • 2012-03-26
                • 2020-11-08
                • 1970-01-01
                • 2012-05-28
                • 1970-01-01
                相关资源
                最近更新 更多