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



所以我想写数据,它以JSON字符串的形式编码到Cassandra表中。我做了以下步骤:

  • 创建一个Cassandra表,其中包含具有JSON字符串所有属性的列。以下是cql:
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';
  • 编写一个python Cassandra客户端,将JSON负载中的数据写入Cassandra。以下是进行INSERt查询的代码片段(msg.value是json字符串(:
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表中数据的主键。问题是,并不是所有的记录都被写入Cassandra,只有时间戳属于某一组的记录。我知道这一点是因为我已经生成了大约100条消息,并且没有收到任何写入错误,但表的内容只有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表,并且您正在写入的数据与表中已有的数据具有相同的主键,则会覆盖它。所有插入都是有效的insert/update,因此当您第二次使用相同的主键值时,它会更新。

至于解决方案-这是骗子-主键必须与它的名称保持一致-它是主键,例如唯一的-即使它是时间戳而不是浮点,你也应该在主键中至少有一个其他字段(如物联网唯一标识符(,这样在同一时间从两个不同设备读取的两个读数就不会冲突。

在Cassandra中,您可以根据访问数据的方式对数据和密钥进行建模,而不知道主键(Partition+Clustering密钥(应该是什么。理想情况下,您还需要了解数据的基数和选择性。

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

这里要添加到上面的具体问题是,数据超过了浮点存储的精度——限制了有效值并使它们完全相同。如果将浮点值更改为双精度,则它会存储数据,而不会将值限制为相同的值,这会导致追加而不是插入新行。(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

最新更新