【问题标题】:Schemaless Data Cache: NoSQL or Other Alternatives?无模式数据缓存:NoSQL 还是其他替代方案?
【发布时间】:2011-03-29 13:36:33
【问题描述】:

我正在评估一些 NoSQL 实现(目前是 RavenDB 和 MongoDB),作为解决一组特定要求的方法,这些要求涉及无模式数据的存储/检索。我想就 NoSQL 是否是我应该研究的方向,或者是否还有其他(可能更简单)选项获得一些反馈。

本质上,我们有一个软件产品(除其他外)定义了一个基本领域模型,该模型由几个相关实体组成,每个实体都有许多属性(键/值)。当我们向客户发布时,我们与他们一起设置属性和值,这本质上是系统的配置。这相当简单,并且因为设计是预先知道的,所以我们不需要任何动态来实现这一点并使其执行(我们将使用 RDBMS)。属性不是预先知道的,但这也不是问题,因为系统的这一部分几乎围绕属性模型展开。

问题在于,对于不同的客户,在我们发布并投入生产之后,我们发现我们需要查询我们在编译和发布代码时(以及在我们配置之前)一无所知的特定属性数据集客户的属性)。我们基本上需要从我们可以存储的属性映射中生成数据(我们不会预先知道结构),然后以我们无法预料的方式查询存储的数据。现在的想法是,我们可以创建在处理过程中受到影响的钩子,并允许我们插入库(可能通过 MEF)创建数据以便存储,然后在需要时查询它(不是为了报告——通常用于创建额外的数据/属性)。

(请注意,创建挂钩和插件库是一个单独的问题,并不打算成为此问题的一部分。)

一种常见的情况可能是:“我想知道 xxx 在过去 10 天内发生了多少次”。所以我会创建一个插件来识别 xxx 已经发生,并将其写入带有日期/时间的数据存储。然后我会创建另一个插件(可能在同一个 DLL 中)来执行查询,并向模型添加一个名为“CountOfxxxInLast10Days”的属性。 另一种情况可能是创建可配置的查找。因此,我可能有一个在启动时运行的插件,以创建/更新可以将一个属性值转换为另一个属性值的查找数据表,或者(更有可能)将转换为查找值的一系列值。因此,转换插件可能会添加一个包含以下列的表:bottom_value、top_value、multiplier,并且查询插件将使用属性值查询该表,例如“SELECT multiplier FROM table WHERE [attribute_value] BETWEEN bottom_value AND top_value”。结果可能会将结果添加到名为“乘数”的属性中。

在某些情况下,旧数据可能会在指定时间段后被清除。在上述第一个场景中,可能需要从存储/缓存中删除超过十天的数据。

在其他情况下,数据需要永久保存,例如上面的第二种情况。有可能这些数据可以在启动时简单地重新创建,而不是保存在永久存储中。

附加要求:

  • 可以备份数据存储/缓存 并在线恢复
  • 可以从 发生崩溃时的最后备份
  • 数据在机器等事件中幸存下来 重启
  • 经过验证/生产测试的技术

我们目前非常致力于 .Net 平台,因此任何选项都必须具有可靠的 .Net 客户端/API。

【问题讨论】:

    标签: .net mongodb caching schemaless nosql


    【解决方案1】:

    共有三种可能的选择,各有利弊。

    重用关系数据库

    您已经将实体存储在关系数据库中。您可以将未定义的属性存储在一个额外的表中,该表有一个KeyValue 列,以及一个引用属性所属实体的EntityId 列。基本上,您将使用数据库的一部分作为键值存储。

    优点:

    • 您的所有数据都存储在一个数据库中,这意味着:
      • 您可以在单个查询中检索实体及其所有属性,
      • 您的应用程序不太复杂,因为它只需要与单个数据库交互。
    • 您可以获得关系数据库的所有 ACID 优势。

    缺点:

    • 关系数据库不是为键值存储而构建的,因此您可能会遇到性能问题。但是,除非您计划存储非常非常多的属性,否则我预计对性能的影响很小。

    使用键值对存储

    键值对存储,例如RedisRiak,或更高级的Apache Cassandra,针对存储键值对进行了优化(这并不奇怪......)。您可以在 RDBMS 旁边使用键值存储,专门用于存储属性,同时将实体保留在 RDBMS 中。

    优点:

    • 比从 RDBMS 获得的性能更好,尤其是在处理大量数据时。
    • 更容易横向扩展,因为它们不受 ACID 属性的限制。

    缺点:

    • 没有保证的 ACID 属性,而是所谓的eventual consistency,这意味着存储的数据在服务器之间可能并不总是一致的。但是,只有在向外扩展时,您才需要处理这个问题。此外,大多数键值存储允许您调整其一致性方面的严格性,以帮助克服这个问题。
    • 您的应用程序将在两个独立的数据库上运行,从而增加了您的应用程序的复杂性。

    使用文档数据库

    您可以使用文档数据库仅存储属性。但您也可以冒险将所有内容存储在文档数据库中,包括您的实体。

    优点:

    • 您的所有数据都存储在一个数据库中,这意味着:
      • 您可以在单个操作中检索实体及其所有属性,就像您将整个实体(包括其属性)存储在单个文档中一样。
      • 您的应用程序不太复杂,因为它只需要与单个数据库交互。
    • 更容易横向扩展,因为它们不受 ACID 属性的限制。
    • 文档数据库不仅限于键值对,因此,如果您需要存储更复杂的属性,您已经可以开始了。

    缺点:

    • 没有 ACID 保证,就像键值存储一样。不过,大多数文档数据库都可以进行调整以克服一致性问题。
    • 无法理解 RDBMS 中的实体之间的关系。关系模型是规范化的,而文档是非规范化的,以克服具有许多关系的问题。这可能是也可能不是一个很大的缺点,具体取决于您的确切域模型。

    成熟的文档数据库技术

    Apache CouchDBquite a list of applications 使用它并从 Stack Overflow 社区接收 positive feedback。它有几个drivers for .NET,但我无法告诉你这些驱动程序有多成熟。

    MongoDB 有一个令人印象深刻的list of production employments。有三个主要的drivers for .NET 可用,似乎都属于good quality

    RavenDB 为 .NET 平台设计了出色的支持。但是,我无法找到在 RavenDB 上运行的大型生产环境的示例。不过,我认为这绝对值得探索。

    我在生产环境中对它们中的任何一个都没有太多的实践经验,所以我不知道备份/恢复它们到底有多容易。但考虑到这些 NoSQL 系统不像 RDBMS 系统那样死板,我想它们应该比 RDBMS 更容易在不停机的情况下备份/恢复。

    【讨论】:

    • 感谢您非常详细的回答。请注意,系统的无模式部分不仅仅是一个键/值存储(看看上面提到的两个场景)。
    • 不客气 :) 是的,我现在意识到您拥有更多的无模式数据,而不仅仅是键值对。在这种情况下,您可以将文档数据库用作单独的数据库,如我在“使用键值存储”中所述。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-08
    • 2011-07-24
    • 2014-02-24
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多