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: 32concurrent_writes: 32concurrent_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 主键是唯一的,INSERTs 和 UPDATEs 本质上是相同的(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 更新无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

presto cassandra 的时间戳比较无法正常工作

cassandra安装配置

Cassandra 不使用本机方法

cassandra 查询超时

Oracle 到 Apache Cassandra 数据迁移

cassandra集群缩容与剔除问题节点