在cassandra计数器表中设置最小计数器值

时间:2016-05-14 05:15:52

标签: cassandra cql

在cassandra中有任何方法可以在计数器列中定义计数器的最小值。假设当计数器值达到0时,即使我减少操作,它也不应低于此值。

1 个答案:

答案 0 :(得分:0)

没有。您的计数器初始化为值0,您可以递增它,递减它,并查询其值。它是(-2 ^ 64和2 ^ 63 - 1)之间的整数。当你达到最小/最大值时,总和/减法会溢出。

如果您尝试处理应用程序中的逻辑,那么只有1个应用程序可以编写,但您可能有多个应用程序,这将很容易。如果您的应用程序位于可以使用锁的同一系统上,那将是可行的,我再次猜测不是这种情况,而且性能会下降。在分布式环境中,您需要能够获得分布式锁,性能会受到影响。

如果确实希望使用Cassandra实现此功能,您可以使用以下策略模拟它:

<强> 1。表格定义

CREATE TABLE test.counter (
    my_key tinyint,
    my_random uuid,
    my_operation int,
    my_non_key tinyint,
    PRIMARY KEY ((my_key), my_operation, my_random)
);

此表将用于跟踪您正在运行的增量/减量操作。几点说明:

  • 分区键my_key将始终使用相同的值:0。它用于在同一分区键中并置所有操作(incrementmente / decremente)。
  • my_random值必须是无任何生成的随机值 碰撞的机会。 uuid可以用于此。如果没有此列,则执行两次相同的操作(例如递增10)将仅存储一次。每个操作都有自己的uuid。
  • my_operation跟踪您执行的增量/减量值。
  • my_non_key是一个虚拟列,我们将用它来查询写时间戳,因为我们无法在主键列上查询它。我们将始终将my_non_key设置为0。

<强> 2。计数器初始化 您可以使用以下命令将计数器初始化为零,

INSERT INTO test.counter  (my_key , my_random, my_operation, my_non_key ) VALUES
( 0, 419ec9cc-ef53-4767-942e-7f0bf9c63a9d, 0, 0);

第3。计数器增量 假设您添加一些数字,例如10.您可以通过插入相同的分区键0,新的随机uuid和值10来实现:

INSERT INTO test.counter  (my_key , my_random, my_operation, my_non_key) VALUES
( 0, d2c68d2a-9e40-486b-bb69-42a0c1d0c506, 10, 0);

<强> 4。减计数 假设您现在减去15:

INSERT INTO test.counter  (my_key , my_random, my_operation, my_non_key ) VALUES
( 0, e7a5c52c-e1af-408f-960e-e98c48504dac, -15, 0);

<强> 5。计数器增量 假设你现在加1:

INSERT INTO test.counter  (my_key , my_random, my_operation, my_non_key ) VALUES
( 0, 980554e6-5918-4c8d-b935-dde74e02109b, 1, 0);

<强> 6。反查询 现在,假设你要查询你的计数器,你需要运行:

SELECT my_operation, writetime(my_non_key), my_random FROM test.counter WHERE my_key = 0;

将返回:0; 10; -15; 1带有写入的时间戳。您的应用程序现在有所有信息来计算正确的值,因为它知道增加/减少操作发生的顺序。当计数器朝向负值达到零时,这当然是必要的。在这种情况下,您的应用程序应该能够计算出正确的值,即1。

<强> 6。清理 在定期间隔或查询计数器时,您可以将值组合在一起并在批处理语句中删除旧值以确保原子性,例如:

BEGIN BATCH
DELETE FROM test.counter WHERE my_key = 0 AND my_operation = -5 and my_random = e7a5c52c-e1af-408f-960e-e98c48504dac;
DELETE FROM test.counter WHERE my_key = 0 AND my_operation = 0 and my_random = 419ec9cc-ef53-4767-942e-7f0bf9c63a9d;
DELETE FROM test.counter WHERE my_key = 0 AND my_operation = 10 and my_random = d2c68d2a-9e40-486b-bb69-42a0c1d0c506;
INSERT INTO test.counter  (my_key , my_random, my_operation, my_non_key ) VALUES (0, ca67df54-62c7-4d31-a79c-a0011439b486, 1, 0);
APPLY BATCH;

最后的笔记