cassandra数据建模物联网最佳实践

nuypyhwy  于 2021-06-15  发布在  Cassandra
关注(0)|答案(1)|浏览(270)

我对Cassandra相当陌生,我正在努力了解如何为物联网传感器设计我的table。
这个想法是有几个设备,每个设备上都连接有几个传感器,定期发送数据(每个传感器每天每个设备最多发送200000个值)
我想能够查询一个传感器的最新值为一个传感器和设备的具体列表在或多或少的实时传感器。此外,设备并不总是发送数据,可能会长时间停机。
读了很多书之后,我想到了这样的东西

CREATE TABLE "sensor_data" (
    deviceid TEXT,
    sensorid TEXT,
    ts timestamp,
    value TEXT,
    PRIMARY KEY ((deviceid, sensorid), ts)
) WITH CLUSTERING ORDER BY (ts DESC);

这背后的想法是对每个设备和传感器执行一个查询,例如

Select deviceid, sensorid, ts, value where deviceid = "device1" and sensorid = "temperature" limit 1

对每个设备和传感器运行这个。它并不是一个查询就可以全部返回(这将是理想的),但是它似乎足够快,可以为一些设备运行100个左右的传感器(有可能并行查询)。
不过,从我目前所读的内容来看,我知道这会给我的行带来很多列,而且可能会因为长期存储和cassandra限制而变得复杂。
我在想,也许像这样在表中添加日期之类的内容(在一些博客和指南中可以看到)可能是个好主意

CREATE TABLE "sensor_data" (
    deviceid TEXT,
    sensorid TEXT,
    date TEXT
    ts timestamp,
    value TEXT,
    PRIMARY KEY ((deviceid, sensorid, date), ts)
) WITH CLUSTERING ORDER BY (ts DESC);

然后像这样询问

Select deviceid, sensorid, date, ts, value where deviceid = "device1" and sensorid = "temperature" and date = "2018-11-14" limit 1

这有道理吗?感觉它可能会缓解存储问题,并允许在将来更轻松地存档旧数据。但是,如果某个特定传感器和设备停机一天或更长时间,我该如何查询该设备的最新值?我真的需要查询1天吗?如果没有找到任何东西,就查询前一天等等(可能只限于最后几天左右)?
Cassandra有没有更好的方法来处理这个问题,或者我的方向是对的?

n3schb8v

n3schb8v1#

问题的一部分,你会遇到的是,每个传感器将有20万读数每天。通常,您希望将每个分区的行数控制在100k以下。所以,你的第二个想法(把约会作为pk的一部分)可能有性能问题。
其实你要做的就是我们所说的“扣扣”;如何将事物组合在一起,以便查询可用且性能良好。
要真正帮助解决这个问题,我们需要了解更多的信息:
你有多少台设备?这个数字会增长还是有限的?
用简单的英语来说,你想回答的问题是什么?
根据您的答案(如下)将此纳入答案:
好吧,这里有一个潜在的想法。。。
不过,我们确实关心bucketing,以尽量保持分区中100k/分区的最佳行数。
你需要两张table:
查阅表格
传感器工作台
查找表将类似于:

CREATE TABLE lookup-table (
deviceid TEXT,
sensor-map MAP,
PRIMARY KEY (deviceid)
);
``` `deviceid` 是每个设备的唯一id `sensor-map` 是给定设备具有的传感器的jsonMap,以及该特定传感器对应的唯一id(例如{温度:183439,湿度:84543292,其他传感器:blah})
这样,每个设备都有一个可用的传感器Map
查询示例如下: `SELECT * FROM lookup-table WHERE deviceid = 1234;` 另一种方法是为每种类型的传感器设置单独的列,并将每个传感器的唯一id作为一个值
传感器表如下所示:

CREATE TABLE sensor_data (
sensorid TEXT,
sensor_value (whatever data type fits what you need),
ts TIMESTAMP,
reading_date date,
time_bucket int,
PRIMARY KEY ((reading_date, sensorid, time_bucket), ts)
) WITH CLUSTERING ORDER BY (ts DESC);

由于每个传感器每天将获得20万个读数,我们希望每个分区的行数不超过10万行,这意味着我们希望每天为每个传感器做两个分区
你怎么能把桶装起来?你应该在两分钟内完成parts:you need 每天提桶;每个传感器每天都有一个新的分区( `reading_date` )把每天分成两部分(根据你期望的阅读量);上午或下午;am等于bucket 1,pm等于bucket 2。或者使用24小时制,其中0-1200等于1,1300-2399等于2
在您的应用程序中提供 `sensorid` 以及 `time_bucket` 将来自您实际请求查询的时间(例如,如果时间是1135小时,那么 `time_bucket = 1` )以及 `reading_date` 将来自您查询的实际日期
因为你和 `ts DESC` 然后,它将检索给定对象的最新读数 `sensorid` . 所以看起来 `SELECT * from sensor_data WHERE reading_date = 12/31/2017 AND sensorid = 1234 AND time_bucket = 1 LIMIT 1;` 通过保持 `ts` 作为一个聚类列,您将能够保留给定传感器的所有读数;不会覆盖任何内容
重要的是要知道:这是伟大的,如果有一个均匀分布的传感器读数在整个24小时的一天。然而,如果你早上阅读量很大,而下午一点也没有,那么这就不是一个平衡点,我们必须想出另一种方法来解决这个问题。但是,我想你知道发生了什么。
要查询:
将有一个查询来检索所有 `sensorid` 一个装置有;一旦你有了这些 `sensorid` ,然后可以将其用于下一步
每个查询将有n个查询 `sensor_value` 对于每个 `sensorid` 因为我们是通过 `time_bucket` ),则应该在所有分区中均匀分布
最后:给我最新的 `sensorid` 在给定的值下,有几种不同的方法。。。
运行spark作业:为此,必须提升和移动数据才能运行spark查询
使用datastax enterprise:使用dse,您有一个基于spark的集成分析组件,因此您可以运行spark作业,而无需管理单独的spark集群。披露:顺便说一句,我在那里工作
创建一个额外的cassandra(c*)表并进行一些并行写入
对于附加的c*表:

CREATE TABLE sensor_by_value (
sensor-value INT,
ts TIMESTAMP,
sensorid TEXT,
reading_date DATE,
time_bucket INT,
PRIMARY KEY ((sensor-value, reading_date), ts)
) WITH CLUSTERING ORDER BY (ts DESC);

你一定要在这里花些时间做些练习:
请记住,我们不希望每个分区的行数超过10万行
您必须了解可能的值(范围)
每次读数的频率
如果你有100台设备,100个传感器,并且每个传感器每天的读数高达200k,那么你有可能每天读取多达2b个传感器读数。。。
通常,我让我的客户做的是对他们的数据进行一些分析,以了解这些信息,这样你就可以确保对这些信息进行解释
你有多少桶将取决于频率
祝你好运!:-)
最终提示
查看压缩策略:特别是时间窗口压缩策略(twcs)和添加 `default_time_to_live` 在初始插入之后,您的数据似乎是不变的
twcs将使压缩的操作开销大大降低,因为您可以根据需要的时间窗口对其进行微调
一 `default_ttl` 这也有助于在您不再需要数据后删除数据的操作开销。
这是否回答和/或满足您试图回答的问题?如果没有,让我知道,我们可以迭代。
要学习所有这些东西,去税务学院接受大量的免费培训。数据建模(DS220)是一门很棒的课程!

相关问题