如何仅存储 Cassandra 中的最新条目?

How to store only most recent entry in Cassandra?

我有一个 Cassandra table 喜欢 :-

create table test(imei text,dt_time timestamp, primary key(imei, dt_time)) WITH CLUSTERING ORDER BY (dt_time DESC);

Partition Key is: imei
Clustering Key is: dt_time

现在我只想为每个分区键在此 table(基于时间)中存储最近的条目。 假设我在 table 中插入条目,其中每个 imei

都有一个条目

现在假设 imei 98838377272 dt_time 是 2017-12-23 16.20.12 现在对于相同的 imei 如果 dt_time 像 2017-12-23 15.20.00 那么这个条目不应该插入那个Cassandra table.

但是如果时间到了 2017-12-23 17.20.00 那么它应该被插入并且前一行应该被替换为这个 dt_time.

首先,要仅存储 table 中的最后一个条目,您需要从主键中删除 dt_time - 否则您会为每个时间戳将条目插入到数据库中。

Cassandra 支持所谓的 lightweight transactions 允许在插入数据之前检查数据。

所以如果你只想在 dt_time 小于新时间时更新条目,那么你可以使用类似的东西:

首先插入数据:

> insert into test(imei, dt_time) values('98838377272', '2017-12-23 15:20:12');

尝试同时更新数据,否则可以更小

> update test SET dt_time = '2017-12-23 15:20:12' WHERE imei = '98838377272' 
   IF dt_time < '2017-12-23 15:20:12';

 [applied] | dt_time
-----------+---------------------------------
     False | 2017-12-23 15:20:12.000000+0000

这将失败,因为从 applied 等于 False 可以看出。我可以用更大的时间戳更新它,它会更新:

> update test SET dt_time = '2017-12-23 15:20:12' WHERE imei = '98838377272' 
   IF dt_time < '2017-12-23 16:21:12';

 [applied]
-----------
      True

这有几个问题:

  1. 如果条目尚不存在,它将不起作用 - 在这种情况下,您可以尝试在尝试更新之前使用 INSERT ... IF NOT EXISTS,或者使用 [= 预填充数据库18=] 数字

  2. 轻量级事务会给集群带来开销,因为数据应该在写入之前读取,这可能会给服务器带来很大的负载,并降低吞吐量。

实际上你不能 "update" 集群键,因为它是主键的一部分,所以你应该删除 dt_time 上的集群键。

然后您可以使用轻量级事务更新行,该事务检查新值是否在现有值之后。

cqlsh:test> CREATE TABLE test1(imei text, dt_time timestamp) PRIMARY KEY (imei);

cqlsh:test> INSERT INTO test1 (imei, dt_time) VALUES ('98838377272', '2017-12-23 16:20:12');
cqlsh:test> SELECT * FROM test1;

 imei        | dt_time
-------------+---------------------------------
 98838377272 | 2017-12-23 08:20:12.000000+0000

(1 rows)

cqlsh:test> UPDATE test1 SET dt_time='2017-12-23 15:20:00' WHERE imei='98838377272' IF dt_time < '2017-12-23 15:20:00';

 [applied] | dt_time
-----------+---------------------------------
     False | 2017-12-23 08:20:12.000000+0000

cqlsh:test> UPDATE test1 SET dt_time='2017-12-23 17:20:00' WHERE imei='98838377272' IF dt_time < '2017-12-23 17:20:00';

 [applied]
-----------
      True

“15:20:00”的更新将 return 'false' 并告诉您当前值。

“17:20:00”的更新将 return 'true'

参考:https://docs.datastax.com/en/cql/3.3/cql/cql_using/useInsertLWT.html

您可以在插入语句中使用 TIMESTAMP 子句将数据标记为最新:

Marks inserted data (write time) with TIMESTAMP. Enter the time since epoch (January 1, 1970) in microseconds. By default, Cassandra uses the actual time of write.

从主键中删除 dt_time 以仅存储 imei

的一个条目
  1. 插入数据并指定时间戳为 2017-12-23 16.20.12
  2. 插入数据并指定时间戳为 2017-12-23 15.20.00

在这种情况下,select by imei 将 return 记录最近的时间戳(从点 1 开始)。

请注意,如果您的 dt_time(将指定为时间戳)小于当前时间,则此方法有效。换句话说,select 查询将 return 具有最近时间戳但在当前时间之前的记录。如果您插入的数据的时间戳大于当前时间,您将在该时间戳到来之前看不到该数据。