代码之家  ›  专栏  ›  技术社区  ›  Phil Sandler

无模式数据缓存:NoSQL还是其他替代方案?

  •  2
  • Phil Sandler  · 技术社区  · 14 年前

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

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

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

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

    一个常见的场景可能是:“我想知道在过去10天内,XXX发生了多少次”。因此,我将创建一个插件,它将识别出发生了XXX,并将其写入具有日期/时间的数据存储区。然后,我将创建另一个插件(可能在同一个dll中)来执行查询,并向模型添加一个名为“countofxxximinst10days”的属性。 γ 另一个场景可能是创建可配置的查找。因此,我可能有一个插件在启动时运行,用于创建/更新查找数据表,该表可以将一个属性值转换为另一个属性值,或者(更可能)转换为查找值的一系列值。因此,转换插件可能会添加一个具有以下列的表:Bottom_Value、Top_Value、乘数,而查询插件将使用属性值查询表,例如“从表中选择乘数,其中[属性_Value]介于Bottom_Value和Top_Value之间”。结果可能会将结果添加到属性called“乘数”中。

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

    在其他情况下,数据需要永久保存,就像上面的第二个场景一样。这种数据可能只是在启动时重新创建,而不是保存在永久存储中。

    附加要求:

    • 可以备份数据存储/缓存 并在联机时恢复
    • 可以从 发生崩溃时的最后一次备份
    • 数据可以在像机器这样的事件中生存 重新启动
    • 经验证/生产测试的技术

    我们现在非常致力于.NET平台,所以任何选项都必须有一个可靠的.NET客户端/API。

    1 回复  |  直到 7 年前
        1
  •  7
  •   Community Ian Goodfellow    7 年前

    有三种可能的选择,每种都有利弊。

    重用关系数据库

    您已经将实体存储在关系数据库中了。可以将未定义的属性存储在具有 Key Value 列和 EntityId 引用属性所属实体的列。基本上,您将使用数据库的一部分作为键值存储。

    优势:

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

    缺点:

    • 关系数据库不是为关键值存储而构建的,因此可能存在性能问题。但是,我希望性能影响最小,除非您计划存储非常大量的属性。

    使用键值存储

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

    优势:

    • 比从RDBMS获得的性能更好,尤其是在有大量数据的情况下。
    • 更容易扩展,因为它们不受酸性物质的限制。

    缺点:

    • 没有保证的酸性质,但所谓的 eventual consistency 也就是说,存储的数据在服务器之间可能并不总是一致的。但是,如果你要扩大规模,你只需要处理这个问题。此外,大多数关键价值存储允许您调整其一致性方面的严格性,以帮助克服这个问题。
    • 您的应用程序将在两个独立的数据库上运行,这增加了应用程序的复杂性。

    使用文档数据库

    您可以使用文档数据库来存储属性。但您也可以大胆尝试,将所有内容存储在文档数据库中,包括您的实体。

    优势:

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

    缺点:

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

    成熟的文档数据库技术

    Apache CouchDB quite a list of applications 使用它并接收 positive feedback 来自堆栈溢出社区。它有一些 drivers for .NET 但是我不能告诉你这些驱动程序有多成熟。

    MongoDB给人印象深刻 list of production employments . 有三个专业 drivers for .NET 可供选择,似乎都是 good quality .

    RavenDB对.NET的支持非常好,因为它是为.NET平台设计的。但是,我还没有找到在RavenDB上运行的大型生产环境的例子。不过,我认为这绝对值得探索。

    在生产环境中,我对它们中的任何一个都没有太多实际操作经验,因此我不清楚它们备份/恢复有多容易。但是考虑到这些NoSQL系统没有RDBMS系统那么严格,我想它们应该比RDBMS更容易在没有停机的情况下进行备份/恢复。

    推荐文章