Cassandra 更新无法正常工作
Posted
技术标签:
【中文标题】Cassandra 更新无法正常工作【英文标题】:Cassandra Updates not working properly 【发布时间】:2015-11-13 11:29:21 【问题描述】:BoundStatement UpdateTable = new BoundStatement(preparedStatement);
UpdateTable.bind(productId, productname, time);
session.execute(UpdateTable);
我正在使用以下命令来更新 cassandra 表。有时会更新,有时不会。
UPDATE product SET count = count + 1 where productId = ? AND productname = ? AND time = ?;
它从不抛出错误。
这是为什么?
编辑
表结构
CREATE TABLE IF NOT EXISTS product(productId int,productname text,time timestamp , count counter,PRIMARY KEY (productid,productname,time));
【问题讨论】:
集群有多少个节点,读写一致性如何? 集群中只有one
节点和concurrent_reads: 32
、concurrent_writes: 32
、concurrent_counter_writes: 32
【参考方案1】:
通过查看您的(Java?)代码,我无法确定insertUpdateTable
是什么类型的对象。但是bind
方法应该返回一个可以执行的BoundStatement 对象。虽然UpdateTable
确实是一个BoundStatement,但我没有看到您实际上将变量绑定到它。
基于显示的代码数量有限,我在这里看到了两种解决方案:
在session.execute
内部的UpdateTable
上调用bind
方法:
session.execute(UpdateTable.bind(productId, productname, time));
将您的 insertUpdateTable.bind
包裹在 session.execute
中:
session.execute(insertUpdateTable.bind(productId, productname, time));
查看Using Bound Statements 上的 DataStax 文档以及 Java 驱动程序以获取更多信息。
有时会更新,有时不会。
如果您发布了 Cassandra 表定义,它可能会对此有所了解。但重要的是要记住 Cassandra 主键是唯一的,INSERT
s 和 UPDATE
s 本质上是相同的(INSERT
可以“更新”现有值,UPDATE
可以“插入”新值)。有时UPDATE
可能看起来不起作用,因为它可能正在使用相同的键值执行写入。只是需要注意的事情。
另外需要注意的是,UPDATE product SET count = count + 1
只能在两种情况下工作:
count
是一个计数器列。
product
是一个计数器表,仅由键和计数器列组成(所有非计数器列必须是 PRIMARY KEY 的一部分)。
值得注意的是计数器列underwent a big change/improvement with Cassandra 2.1。如果您需要使用计数器并且仍在使用 Cassandra 2.0,则可能值得升级。
【讨论】:
已用表格结构更新问题。这是一个java代码。我说过它永远不会抛出任何错误。但是,有时它会起作用,而有时却不起作用。另外,当我检查日志时,我会看到那里的值。我不知道发生了什么。 @user4974500 问题是,您不会看到错误消息,因为一切在语法上都是正确的。 system.log 在您运行 UPDATE 时是否显示任何相关消息?如果可能,请尝试在 2.1 测试集群上运行它,看看您的结果是否更加一致。【参考方案2】:您说更新有时会起作用,但请注意,如果您曾经使用计数器删除行,则如果不删除表并重新创建它,您将无法再次修改该行。更新似乎会以静默方式失败。更多内容请见CASSANDRA-8491
【讨论】:
【参考方案3】:我在高频写入和更新期间遇到了类似的问题。
随着并发请求数量的增加,最新的绑定很有可能会覆盖之前的绑定参数。所以不是使用单个boundStatement,而是在session.execute中使用preparedStatement.bind()
你可以试试下面的。
而不是使用:
UpdateTable.bind(productId, productname, time);
session.execute(UpdateTable);
使用:
session.execute(preparedStatement.bind(productId, productname, time));
【讨论】:
以上是关于Cassandra 更新无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章