使用 python 客户端将 JSON 数据写入 Cassandra,主键选择问题

Writing JSON data into Cassandra using python client, issue with primary key choice

所以我想将编码为 JSON 字符串的数据写入 Cassandra table。我做了以下步骤:

CREATE TABLE on_equipment (
  ChnID varchar,
  StgID varchar,
  EquipID varchar,
  SenID varchar,
  value1 float,
  value2 float,
  value3 float,
  electric_consumption float,
  timestamp float,
  measurement_location varchar,
  PRIMARY KEY ((timestamp))
) WITH comment = 'A table for the on equipment readings';
session.execute('INSERT INTO ' + table_name + ' JSON ' + "'" + msg.value + "';")

我在执行此操作时没有出现写入错误。

但是,我运行遇到了一个问题:

我拥有的 JSON 数据来自 IoT 来源,我拥有的属性之一是 unix 时间戳。 JSON 记录的示例如下(注意时间戳属性):

{'timestamp': 1598279069.441547, 'value1': 0.36809349674042857, 'value2': 18.284579388599308, 'value3': 39.95615809003724, 'electric_consumption': 1.2468644044844224, 'SenID': '1', 'EquipID': 'MID-1', 'StgID': '1', 'ChnID': '1', 'measurement_location': 'OnEquipment'}

为了插入多条记录,我在Cassandra中定义了时间戳值作为数据的主键table。问题是并非所有记录都被写入 Cassandra,只有时间戳属于特定组的记录。我知道这一点是因为我已经生成了大约 100 条消息并且收到了零个写入错误,但是 table 的内容只有 4 行:

 timestamp  | chnid | electric_consumption | equipid | measurement_location | senid | stgid | value1   | value2   | value3
------------+-------+----------------------+---------+----------------------+-------+-------+----------+----------+----------
 1.5983e+09 |     1 |             0.149826 |   MID-1 |          OnEquipment |     1 |     1 | 0.702309 | 19.92813 | 21.47207
 1.5983e+09 |     1 |              1.10219 |   MID-1 |          OnEquipment |     1 |     1 | 0.141921 |  5.11319 | 78.17094
 1.5983e+09 |     1 |              1.24686 |   MID-1 |          OnEquipment |     1 |     1 | 0.368093 | 18.28458 | 39.95616
 1.5983e+09 |     1 |              1.22841 |   MID-1 |          OnEquipment |     1 |     1 | 0.318357 |  16.9013 |  71.5506

换句话说,Cassandra 正在更新这四行的值,而此时它应该写入所有 100 条消息。

我的猜测是我错误地使用了 Cassandra 主键。时间戳列是 float 类型。

我的问题: 这种行为有意义吗?你能解释一下吗? 我可以使用什么作为主键来解决这个问题? 有没有办法让主键成为Cassandra写入或到达时间?

提前感谢您的帮助!

您已将主键定义为时间戳 - 如果您将数据插入 Cassandra table,并且您正在写入的数据与 table 中已有的数据具有相同的主键,您将覆盖它。所有插入都有效 insert/update,因此当您第二次使用相同的主键值时,它将更新。

至于解决方案 - 这是一个骗局 - 主键必须符合它的名称 - 它是主要的,例如唯一 - 即使它是时间戳而不是浮点数,您也应该在主键中至少有 1 个其他字段(例如 IoT 唯一标识符),以便在完全相同的时间从两个不同设备读取的 2 个读数不会发生冲突.

在 Cassandra 中,您可以根据您打算如何访问数据来对数据和键进行建模 - 不知道不可能知道主键(分区 + 集群键)应该是什么。理想情况下,您还需要了解有关数据基数和选择性的知识。

识别并定义您打算 运行 对数据的查询,这应该指导您的分区键和集群键选择 - 它们共同构成主键。

这里要添加到上面的具体问题是数据超出了浮点数可以存储的精度 - 限制有效值并使它们全部相同。如果将 float 更改为 double,它会存储数据而不将值限制为相同的值 - 这会导致更新插入而不是插入新行。 (JSON 插入部分与问题无关,因为它发生了)

重现问题如下:

 CREATE TABLE on_equipment (
  ChnID varchar,
  timestamp float,
  PRIMARY KEY ((timestamp))
) ;

insert into on_equipment(timestamp, chnid) values (1598279061,'1');
insert into on_equipment(timestamp, chnid) values (1598279062,'2');
insert into on_equipment(timestamp, chnid) values (1598279063,'3');
insert into on_equipment(timestamp, chnid) values (1598279064,'4');

select count(*) from on_equipment;

1

select timestamp from on_equipment;

1.59827904E9

您可以看到该值已四舍五入并设置了上限,所有 4 个值的上限相同,如果您使用较小的数字作为时间戳,它会起作用,但这样做不是很有用。

将其更改为双精度:

CREATE TABLE on_equipment (
  ChnID varchar,
  timestamp double,
  PRIMARY KEY ((timestamp))
) ;

insert into on_equipment(timestamp, chnid) values (1598279061,'1');
insert into on_equipment(timestamp, chnid) values (1598279062,'2');
insert into on_equipment(timestamp, chnid) values (1598279063,'3');
insert into on_equipment(timestamp, chnid) values (1598279064,'4');

select count(*) from on_equipment;

4