【问题标题】:Efficient and scalable storage for JSON data with NoSQL databases使用 NoSQL 数据库对 JSON 数据进行高效且可扩展的存储
【发布时间】:2011-10-29 21:25:06
【问题描述】:

我们正在开展一个项目,该项目应收集日志和审计数据并将其存储在数据存储中以用于存档和某些视图。我们不太确定哪个数据存储适合我们。

  • 我们需要存储小的 JSON 文档,大约 150 字节,例如"audit:{timestamp: '86346512',host':'foo',username:'bar',task:'foo',result:0}""journal:{timestamp:'86346512',host':'foo',terminalid:1,type='bar',rc=0}"
  • 我们预计每天约有 100 万个条目,大约 150 MB 数据
  • 数据将被存储和读取,但不会被修改
  • 数据应以有效的方式存储,例如Apache Avro 使用的二进制格式
  • 保留时间后数据可能会被删除
  • 自定义查询,例如'get audit for user and time period''get journal for terminalid and time period'
  • 为故障安全复制数据库
  • 可扩展

目前我们正在评估 NoSQL 数据库,例如 Hadoop/Hbase、CouchDB、MongoDB 和 Cassandra。这些数据库是适合我们的数据存储吗?他们中的哪一个最适合? 有更好的选择吗?

【问题讨论】:

    标签: json mongodb hadoop couchdb cassandra


    【解决方案1】:
    • 一百万次插入/天大约是 10 次插入/秒。大多数数据库都可以处理这个问题,而且它远低于我们在合理硬件上从 Cassandra 获得的最大插入率(50k 插入/秒)

    • 您的要求“在保留时间后可能会删除数据”非常适合 Cassandra 的 TTL 列 - 当您插入数据时,您可以指定将其保留多长时间,然后后台合并进程将在达到该数据时删除该数据超时。

    • “数据应该以有效的方式存储,例如 Apache Avro 使用的二进制格式” - Cassandra(像许多其他 NOSQL 存储一样)将值视为不透明的字节序列,因此您可以根据需要对值进行编码。您还可以考虑将值分解为一系列列,这样您就可以进行更复杂的查询。

    • 自定义查询,例如“获取用户和时间段的审核” - 在 Cassandra 中,您可以通过将行键作为用户 ID 并将列键作为事件时间来对此进行建模(大多数可能是timeuuid)。然后,您将使用 get_slice 调用(甚至更好的 CQL)来满足此查询

    • 或“获取终端 ID 和时间段的日志” - 如上所述,行键为终端 ID,列键为时间戳。需要注意的一点是,在 Cassandra(与许多无连接存储一样)中,通常会多次插入数据(以不同的排列方式)以针对不同的查询进行优化。

    • Cassandra 具有非常复杂的复制模型,您可以在其中为每个操作指定不同的一致性级别。 Cassandra 也是非常可扩展的系统,没有单点故障或瓶颈。这确实是 Cassandra 与 MongoDB 或 HBase 之类的东西之间的主要区别(不是我想点燃火焰!)

    说了这么多,更传统的数据库和简单的主从复制可以轻松满足您的要求,这里没有什么太繁重的地方

    【讨论】:

    • 我忘了提到 json 数据我的可变字段、固定字段和可变字段。 RDBMS 需要一个固定的模式。所以搜索会导致全文搜索,而且总是很昂贵。我们需要的是具有合理索引的灵活存储。
    • HBase 适用于稀疏列,这意味着您可以随时添加新列(不是列族),并且任何给定的行都不需要所有列的值。但是,这种设计使得以与传统 RDBMS 相同的方式进行查询并不容易(尽管仍然可能)。有时不那么快,但在某个时间点之后,RDBMS 会崩溃,而 HBase 将继续运行,并以可预测的报告时间运行,只要您确定 X 数量的数据需要多长时间。
    【解决方案2】:

    Avro 支持模式演化,非常适合此类问题。

    如果您的系统不需要低延迟数据加载,请考虑将数据接收到可靠文件系统中的文件中,而不是直接加载到实时数据库系统中。与实时数据库系统相比,保持可靠的文件系统(例如 HDFS)运行更简单,也不太可能出现中断。此外,职责分离可确保您的查询流量永远不会影响数据收集系统。

    如果您只需要运行少量查询,您可以将文件保留为原始格式并编写自定义地图缩减以生成您需要的报告。如果您想要更高级别的接口,请考虑在本机数据文件上运行 Hive。 Hive 将允许您对原始数据文件运行任意友好的类似 SQL 的查询。或者,由于您每天只有 150MB,您可以将其批量加载到 MySQL 只读压缩表中。

    如果出于某种原因您需要复杂的交互式系统、HBase 或 Cassandra,或者可能非常适合,但请注意,您将花费大量时间玩“DBA”,而 150MB/天的数据太少了你可能不需要复杂性。

    【讨论】:

      【解决方案3】:

      我们正在使用 Hadoop/HBase,我查看了 Cassandra,他们通常使用行键作为最快检索数据的方法,当然(至少在 HBase 中)您仍然可以应用它对列数据进行过滤,或者在客户端进行过滤。例如,在 HBase 中,您可以说“给我从 key1 到但不包括 key2 的所有行”。

      因此,如果您正确设计密钥,您可以获得 1 个用户、1 个主机或 1 个主机上的 1 个用户的所有内容,或类似的东西。但是,它需要一个设计合理的密钥。例如,如果您的大多数查询需要使用时间戳运行,您可以将其作为键的一部分。

      您需要多久查询一次数据/写入一次数据?如果您希望运行您的报告并且如果它需要 10、15 或更多分钟(可能)没问题,但是您做了很多小写入,那么 HBase w/Hadoop 执行 MapReduce(或使用 Hive 或 Pig 作为更高级别的查询语言)会很好用。

      【讨论】:

      • 数据会被永久写入,负载取决于服务是否会被执行。查询将在用户交互时临时执行。查询必须在合理的时间内执行。所以 Map-Reduce 不可行对吧?
      • 嗯,对您来说合理的持续时间是多少?执行时间部分取决于数据量(记录数),部分取决于 Hadoop 集群的大小。例如,在我们的 6 节点集群上,6M 左右的记录大约需要 5-7 分钟,但每条记录都有很多与之关联的数据。这是 HDFS 的直接 MapReduce,而不是 HBase 的 MapReduce,它可以同样快或更快,具体取决于扫描。
      【解决方案4】:

      如果您的 JSON 数据具有可变字段,那么像 Cassandra 这样的无模式模型可以很好地满足您的需求。我会将数据扩展为列,而不是以二进制格式存储,这样更容易查询。以给定的数据速率,填满 1 TB 磁盘需要 20 年,所以我不用担心压缩问题。

      对于您提供的示例,您可以创建两个列族,即 Audit 和 Journal。行键将是 TimeUUID(即时间戳 + MAC 地址,将它们变成唯一键)。那么您提供的审计行将有四列,host:'foo'username:'bar'task:'foo'result:0。其他行可能有不同的列。

      对行键的范围扫描将允许您在一段时间内有效地查询(假设您使用 ByteOrderedPartitioner)。然后可以使用二级索引查询用户和终端。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-18
        • 2012-12-20
        • 1970-01-01
        • 2012-10-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多