Cassandra:带有动态列/源的时间序列

时间:2016-07-06 10:30:30

标签: cassandra cql database nosql

关于使用cassandra存储时间序列存在很多问题,但没有人适合我们的问题,因为它们都假设一个固定的数据源和已知的列名。

关于我们的问题: 我们正在开发一个流数据引擎,它可以连接到不同的数据源,引擎以连续流的形式接收数据。 因此,我们有两个名为energyweather的数据源。每个传入流(或数据源)都有自己的唯一密钥,通常也有自己的模式,例如:

带有架构ID 1

来源energy可能包含以下内容:

timestamp | volts | amps | watts | state
1467795743173 | 210.4 | 2.3 | 290  | "up"
1467795744173 | 212.1 | 2.1 | 287  | "up"
1467795745173 | 213.1 | 2.2 | 242  | "up"
...
带有架构ID 2

来源weather可能包含以下内容:

ts | condition | temp
1467795740632 | "cloudy" | 33.1
1467795741381 | "cloudy" | 33.4
...

现在我们希望能够将流存储到cassandra中,以便以后可以用它们“重放”记录的流,获取历史结果(例如用于分析)以及使用特定的流来丰富/加入传入的流存储的数据值(例如,显示/比较当前能量值与一周前记录的能量值)。总之,我们基本上需要这些东西:

  • 按顺序阅读certian来源ID
  • 获取某个源ID的范围(例如,在2016-07-06之间从10:00到11:00之间从设备ID 2中获取所有内容)
  • 保存任意列(除了固定的时间戳列),因为我们事先不知道架构。

由于我们是cassandra的新手,我们目前不知道对表格和列进行建模的最佳方法是什么。

类似问题的大多数答案都不会面临使用未知模式的可能性(它们都假设存在时间戳,deviceId和double值)并且只面临主/部分密钥的问题。

我们读到了两个选项:

  1. 我们是否应该有一张桌子,例如datapoints,其中包含source-ID + day作为分区键的所有数据?但是我们如何在这里处理动态列?我们是否必须将整个元组序列化为单个公共列,例如将energydata和天气数据全部放在一个名为value的列中。
  2. 所以我们有这张表:

    CREATE TABLE datapoints (
     sourceid bigint,
     date text, 
     time timestamp, 
     value text,
      PRIMARY KEY ((sourceid, date), time)
     )
    

    显然,我们不能在原始值上使用aggreate或其他函数(例如瓦特,安培或临时值)。

    另一种可能性是为每个数据源创建一个表,例如使用day作为分区键:

    CREATE TABLE energy_1 (   
     date text, 
     time timestamp, 
     volts double,
     amps double,
     watts double,
     state text,
      PRIMARY KEY (date, time)
     )
    
    CREATE TABLE weather_2 (
     date text, 
     time timestamp, 
     condition text,
     temp double,
      PRIMARY KEY (date, time)
     )
    

    由于数据将使用日期进行分配,是否可以获取数据,例如一周还是不可能?尽管可能存在多个具有相同模式的数据源(例如,两个能源数据源),但我们并不知道它,这很少见。因此,使用device-id作为分区密钥是没有意义的,因为每个模式通常只有一个设备密钥。

    但第二种解决方案看起来也不太合适。

    我们希望有人也解决了类似问题并提出了一些建议吗?!

    备注:我们不想使用其他时间序列db:)

2 个答案:

答案 0 :(得分:1)

考虑使用地图作为数据值:

CREATE TABLE datapoints (
  sourceid bigint,
  date text, 
  time timestamp, 
  values map<text, text>,
  PRIMARY KEY ((sourceid, date), time)
 )

您还可以将地图用于不同的数据类型:

CREATE TABLE datapoints (
  sourceid bigint,
  date text, 
  time timestamp, 
  strvalues map<text, text>,
  intvalues map<text, int>,
  decvalues map<text, decimal>,
  PRIMARY KEY ((sourceid, date), time)
 )

答案 1 :(得分:0)

也许你可以混合使用这两种解决方案:

您可以创建一个包含所有信息的表格,如:

1

插入数据时,可能未指定许多列。但无论如何,cassandra不会在磁盘上存储NULL值。因此,此列表中包含5CREATE TABLE datapoints ( sourceid bigint, date text, time timestamp, value text, volts double, amps double, watts double, state text, condition text, temp double, PRIMARY KEY ((sourceid, date), time) ); 列,并在示例中将变量空间作为表conditions

如果您使用cassandra&gt; = 3.0,yopu可以创建materialized视图来创建特定的表(如tempweather_2)或创建其他方式来读取数据(重新指定分区例如关键)。

希望这可以帮到你。