Cassandra CQL3 条件插入/更新

5

我有一个无序事件列表,我的任务是为它们存储第一次和最后一次出现的时间。

我在Cassandra中有以下列族:

CREATE TABLE events (
   event_name TEXT,
   first_occurrence BIGINT,
   last_occurrence BIGINT,
   PRIMARY KEY (event_name)
);

如果我有一个名为“some_event”的事件,发生次数为123456,那么我想做的事情在MySQL术语中看起来像这样:

INSERT INTO events (event_name, first_occurence, last_occurence)
VALUES ('some_event', 123456, 123456)
ON DUPLICATE KEY UPDATE 
     first_occurrence = LEAST(first_occurrence, 12345), 
     last_occurrence = GREATEST(last_occurrence, 123456)

我将使用Cassandra中的轻量事务来实现这一目标,像这样:
INSERT INTO events(event_name, first_occurrence, last_occurrence) VALUES ('some_event', 12345, 12345) IF NOT EXISTS;
UPDATE events SET first_occurrence = 123456 WHERE event_name='some_event' IF first_occurrence > 123456;
UPDATE events SET last_occurrence = 123456 WHERE event_name='some_event' IF last_occurrence < 123456;

事实证明,CQL3在轻量级事务的IF子句中不允许使用<和>运算符。

那么我的问题是,如何进行这样的条件更新?

2个回答

4
你正在运行哪个版本的Cassandra? 非相等条件与LWTs的支持是通过CASSANDRA-6839在2.1.1中添加的。
cqlsh:test> UPDATE events SET first_occurrence = 123456 WHERE event_name='some_event' IF first_occurrence > 1;

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

1
谢谢,这正是我所需要的。我目前正在运行DataStax社区2.0.9。这意味着我需要切换到“开发”分支。 - board reader

2
Cassandra在写入之前不会进行读取,只有2个例外 - 计数器和“轻量级事务”。因此,您将无法可靠地直接在Cassandra中实现您的场景。即使您读取值然后基于这些值进行更新,由于Cassandra中没有锁定和隔离,并且最终一致性使情况变得更糟,您可能会覆盖其他人的更改。
因此,如果您需要实现类似的功能,则需要在Cassandra之外进行。创建一个同步层,它将提供用于Cassandra写入的中心点,并使该层负责逻辑。只需确保没有写入绕过此层即可。

1
我认为IF column = values和IF column < value比较之间没有太大的区别,因此我仍然认为可以通过轻量级事务找到解决方法。 - board reader
1
你没有理解重点。这不是关于等于和不等于的区别,而是因为在插入或更新时你不知道数据库中的值。因此,在Cassandra中,INSERT是UPDATE的同义词。在4个ACID属性(原子性、一致性、隔离性、持久性)中,Cassandra只提供了2个——A和D。你的例子需要至少一个以上的属性——可能是隔离性,也可能是一致性。这就是为什么我说你必须构建一个在Cassandra之外提供这些属性的东西。 - Roman Tumaykin
1
我认为我们在这里争论的是不同的事情。 轻量级事务确实可以工作,对吧? Cassandra 在轻量级事务上进行了读取-写入操作,类似于以下查询:UPDATE events SET first_occurrence = 123456 WHERE event_name='some_event' IF first_occurrence = 2345678;因此,在实现等于和不等于比较时,我没有看到任何技术上的区别。 - board reader
啊,我不小心删掉了我的评论而不是添加它。LWT为compare-and-set(CAS)操作提供线性一致性。传统上,CAS操作要求期望值等于当前值才能应用更改。CASSANDRA-6839(2.1.1+)允许您使用>,<和其他比较符号,已经为此添加了一个答案。 - Andy Tolbert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接