【问题标题】:Cassandra: High volume sensor data clarificationCassandra:大量传感器数据澄清
【发布时间】:2017-05-24 08:11:12
【问题描述】:

我们正在考虑将我们的时间序列应用程序从 SQL Server 迁移到 Cassandra,因为数据量变得太大,SQL Server 无法处理。我们可以有多达 100 个传感器同时工作(有时一整年,有时更短,但通常至少同时工作 50 个),每个传感器能够以高达 60 Hz 的频率传输多达 20 个不同的测量值(未来可能有 120 个)。

大多数在线资源(例如DataStax)建议将分区划分为“可管理的分区”,这可能低于 1,000,000 行(实际上,低于 50MB 的数据可能是实际指标)。因此,对于 1 Hz 的报告率,将每个传感器数量按一周划分会产生(7 * 24 * 60 * 60) = 604,800 每个分区的测量值:

CREATE TABLE measurements (
    sensor_id       TEXT,
    quantity        TEXT,
    start_of_week   TIMESTAMP,
    offset_seconds  INT,        -- offset from week start (0..604799)
    value           FLOAT,
    PRIMARY KEY ((sensor_id, quantity, start_of_week), offset_seconds)
) WITH CLUSTERING ORDER BY (offset_seconds DESC)

因此,自然地,对于 60 Hz 报告率,我可能会按小时 进行分区,以保持简单并获得每个分区的 (60 * 60 * 60) = 216,000 测量值。或者几个小时,当然。

但是,我对这将如何在实践中发挥作用有一些不确定性。

到目前为止,我们有一个相当非规范化的 SQL Server 数据库,我们会将来自单个传感器的所有 20 个值放在一行中,并且服务器能够跟上(尽管 CPU 一直保持在 ~30%)最多 50 台设备(基本上是每秒 3,000 行,我们假设 SQL Server 的最大速度约为 10,000 行/秒)。不用说,如果每个设备都添加新数量,这根本无法扩展,同时对于报告数量少于 20 个的设备会浪费大量空间。

但是,使用上述 C* 方法,每秒存储的键值对的数量(假设 100 个传感器、20 个测量值、60 Hz)似乎将是每秒 120,000 个

  1. 是否可以通过“基本”3 节点设置来实现这一点?对于这样的插入率,实际上需要多少个 Cassandra 节点?

  2. 将单个数量的所有亚秒 (60 Hz) 值移动到单个 blob 是否会提高性能?这意味着总插入率将是 2,000 个blob,这似乎更易于管理(甚至 60 个 float32 值的 240 字节大小的 blob 似乎也不是那么大)。

    李>

大多数情况下,数据将从包含预先计算的最小/最大/平均聚合的不同表中显示(用户可以随时创建全分辨率范围查询,但范围更小),因此我们的重点是最大化写入吞吐量。如果您认为任何其他模式可能会提供更好的吞吐量(我不知道,可能是多个表/其他一些分区/集群策略),请提出建议。如果它能够更好地满足我们的要求,我们甚至愿意切换到不同的 NoSQL 数据库。

【问题讨论】:

    标签: cassandra time-series nosql


    【解决方案1】:

    是否可以通过“基本”3 节点设置来实现这一点?对于这样的插入率,实际上需要多少个 Cassandra 节点?

    3 节点集群每秒 120,000 次肯定是可能的,但这在很大程度上取决于您的硬件。我预计正常实例的速度为 20k-30k/秒。我坚持的经验法则是 4k/sec/core,但它非常依赖于硬件/负载。

    将单个数量的所有亚秒 (60 Hz) 值移动到单个 blob 中会提高性能吗?这意味着总插入率将是 2,000 个 blob,这似乎更易于管理(甚至 60 个 float32 值的 240 字节大小的 blob 似乎也不是那么大)。

    是的,这将有助于提高吞吐量。

    一些注意事项:

    确保您的客户端在这种负载下有效地执行您的查询,否则您可能会看到瓶颈。使插入异步并根据飞行中的请求应用背压是一个好主意。有批处理,但只有当所有写入都进入同一个分区时才有效。因此,如果您第二次有 60 个读数并将它们全部插入同一个分区,则执行 unlogged 批处理会更快。记录的批次将大大变慢。有一点是,这最终会导致性能变得更糟,但是对于不同的工作负载,这个数字是不同的,所以可能想尝试一下。

    我会为此工作负载推荐 Timed Window Compaction Strategy (TWCS)。

    在 2.x 版本中,每个分区 100mb 是一个很好的限制。在以后的 3.x 版本和 4.x 未来版本中,您在更高版本(即 gb)中会更加安全。也就是说,分区仍然是最低级别,所以如果它们变得太大,它仍然会导致热点,并且它会使维修等事情的效率大大降低。在监控中密切关注最大/平均表分区大小。

    使用offset_seconds 实际上最好是完整的时间戳。当您进行读取时,它会检查最小/最大聚类键与查询的内容以确定要读取的 sstable。每个 sstable 都存储其最小/最大聚类键以优化时间序列。如果您有 TWCS 并且您正在查询一个时间范围,它将能够将 sstables 缩小到相关的。否则它可能会包括很多,因为偏移量将在每个桶中重置并且有重叠。布隆过滤器应该捕获一些具有不同分区键的过滤器,但它会出现误报,并且需要检查所有 sstable 上的布隆过滤器(这是在从最小/最大选择之后完成的,并且远非免费)。这可能看起来有点浪费空间,但它会大大提高阅读效果。

    【讨论】:

    • 谢谢!一个澄清虽然:1)这是否意味着未记录的批次完全跳过提交(事务)日志?由于您提到自己的原因,某些人似乎批次是recommended against,但我不想失去原子性/耐用性。 2) 你知道 C* 吞吐量 以 MB 为单位的一些实用值吗?由于使用 240B 块,插入速率结果为 2000 次插入/秒,但这显然与插入 20B 行不同。
    • (一个答案显然是“你为什么不对其进行分析并自己看看”,但只是对预期的结果有一些粗略的想法 - 我不想建议投资设置这不可能适用于我们的用例)
    • 未记录的批次仍然通过正常的事情,但它跳过了 paxos 的东西和记录的批次经历的双重写入。当您有多个分区时,建议不要(由我包括在内),因为它需要协调器做很多工作并增加它失败的机会,因为它涉及这么多节点。如果批次的所有行都在同一个分区中,尽管它节省了往返和一些开销。 christopher-batey.blogspot.com/2015/02/… 很好地解释了它如何变得更好。
    • 我无法就 mb/sec 的经验法则提供指导。这将取决于磁盘。我强烈建议使用 cassandra-stress 来测试这个和自己的基准测试,你会发现专注于 C* 和客户端更容易。另请注意,我在上面进行了编辑,以包含关于您的聚类索引的注释。
    • 非常感谢所有提示,包括集群提示,直到现在我还没有意识到 sstables 是如何存储数据的(我感觉分区键 + 集群键的行为就像一个复合键稳定的)。如果可以在 DataStax 数据建模示例(传感器用例)中提及这一点,那就太棒了。
    猜你喜欢
    • 2013-05-03
    • 2014-12-11
    • 1970-01-01
    • 2015-12-08
    • 2020-07-12
    • 2019-04-02
    • 1970-01-01
    • 2015-12-30
    • 2015-04-04
    相关资源
    最近更新 更多