我们有一个3节点的cassandra集群(单个dc)和一个表,这些表可以被运行在不同节点上的应用程序访问(读/写)。
在重载情况下,当应用程序的两个示例都试图更新相同的用户条目(例如add attribute)时,我们从 app1
(正在运行) node1
成功-即。 ResultSet#wasApplied
退货 true
). 但是,什么时候 app2
(开 node2
读取数据之前,它正在获取过时的数据 app1
更新了它)。
我想知道为什么会发生这种情况,因为具有串行一致性的ltw应该可以防止这种类型的不一致。非常感谢您的帮助!
提前谢谢!
示例:(基于应用程序日志)
最初,用户具有 A
有价值的 1
两者 app1
以及 app2
正在添加新属性; app1
添加 B:2
以及 app2
添加
C:3 app1
将正确的数据读入内存,添加新属性 B
并成功地给Cassandra写信。日志显示最终的属性列表 A:1
以及 B:2
元组。 app2
读取数据,但只看到 A:1
(从 app1
以及 app2
只有2ms;因此可能以任何顺序发生)。
一次 app2
的写入已完成,结束状态只有 A:1
以及 C:2
,这是不正确的。
更多信息
对表执行读写操作的(准备好的语句)具有以下特征:
write是lwt(如果存在userid,则为on)
在一致性级别为local\u quorum的情况下执行对表的写入
表上的读取以本地\u serial的一致性级别执行
这张table看起来像:
CREATE TABLE my_table(userid ascii, username ascii, attributes map);
更新属性Map时,应用程序内的逻辑是:
User user = dao.getUser(userid);
user.addNewAttribute("key", "value");
dao.update(user);
1条答案
按热度按时间lnxxn5zx1#
因为读/写操作发生在两个不同的节点上,所以我们没有在应用程序级别同步操作。
app2
他在做那件事read
之前app1
开始写了。因此,app1
获取过时数据(不是过时数据)。这个update
操作设置整个Map,而不是在Map中添加/删除元素。我们已经改变了逻辑,所以add/remove操作现在分别执行add(和remove)而不是“read and then set”。
新的prepared语句类似于:
在使用
set