我正在使用 Datastax Cassandra java 驱动程序记录实时交易数据。我为 Cassandra 配置了单个节点、复制因子 1 和一致性级别 ALL。
我经常有不记录但不会失败的写入。 java客户端没有抛出任何错误,异步执行成功回调被调用。 Trace 似乎没有显示任何异常:
[CassandraClient] - Adding to trades memtable on /10.0.0.118[SharedPool-Worker-1] at Mon Dec 22 22:54:04 UTC 2015
[CassandraClient] - Appending to commitlog on /10.0.0.118[SharedPool-Worker-1] at Mon Dec 22 22:54:04 UTC 2015
[CassandraClient] - Coordinator used /10.0.0.118
但是,当我查看 cassandra shell 中的数据时,请注意跳过的 ID(忽略错误日期):
cqlsh:keyspace> select * from trades where [...] order by date desc limit 10;
date | id | price | volume
--------------------------+--------+--------+------------
1970-01-17 19:00:19+0000 | 729286 | 435.96 | 3.4410000
1970-01-17 19:00:19+0000 | 729284 | 436.00 | 17.4000000
1970-01-17 19:00:19+0000 | 729283 | 436.00 | 0.1300000
1970-01-17 19:00:19+0000 | 729277 | 436.45 | 5.6972000
1970-01-17 19:00:19+0000 | 729276 | 436.44 | 1.0000000
1970-01-17 19:00:19+0000 | 729275 | 436.44 | 0.9728478
1970-01-17 19:00:19+0000 | 729274 | 436.43 | 0.0700070
1970-01-17 19:00:19+0000 | 729273 | 436.45 | 0.0369260
1970-01-17 19:00:19+0000 | 729272 | 436.43 | 1.0000000
1970-01-17 19:00:19+0000 | 729271 | 436.43 | 1.0000000
为什么有些插入会悄无声息地失败?指示指向时间戳问题,但我没有检测到模式。
类似问题:Cassandra - Write doesn't fail, but values aren't inserted
最佳答案
写入成功但一些记录丢失的事实表明 C* 正在覆盖丢失的行。您可能看到这种行为的原因是滥用了绑定(bind)语句。
通常人们准备语句:
PreparedStatement ps = ...;
BoundStatement bs = ps.bind();
然后他们发出类似的东西:
for (int i = 0; i < myHugeNumberOfRowsToInsert; i++) {
session.executeAsync(bs.bind(xx));
}
这实际上会产生奇怪的行为,因为绑定(bind)语句 在大多数 executeAsync
调用中都是相同的,并且如果循环足够快以排队(比如) 在驱动程序触发第一个查询之前的 6 个查询,所有提交的查询将共享相同的绑定(bind)数据。一个简单的解决方法是实际发出不同的 BoundStatement:
for (int i = 0; i < myHugeNumberOfRowsToInsert; i++) {
session.executeAsync(new BoundStatement(ps).bind(xx));
}
这将保证每个语句都是唯一的,并且根本不可能覆盖。
关于java - cassandra 大量写入有时会默默地失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34424886/