本文介绍了Cassandra:将列设置为null后写入将随机丢失。这是一个错误,还是我做错了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  @Test 
public void testWriteUpdateRead()throws Exception {
群集集群= Cluster.builder()
.addContactPoint(127.0.0.1 )
.build();
Session cs = cluster.connect();
cs.execute(DROP KEYSPACE if exists readtest;);
cs.execute(CREATE KEYSPACE readtest WITH replication+
= {'class':'SimpleStrategy','replication_factor':1};);
cs.execute(create table readtest.sessions(+
id text primary key,+
passwordHash text,+
););

for(int i = 0; i String sessionID = UUID.randomUUID()。toString();
cs.execute(insert into readtest.sessions(id,passwordHash)values('+ sessionID +',null));
cs.execute(update readtest.sessions set passwordHash ='+ sessionID +'where id ='+ sessionID +');
ResultSet rs = cs.execute(select * from readtest.sessions where id ='+ sessionID +');
row row = rs.one();
assertThat(failed ith time =+ i,row.getString(passwordHash),equalTo(sessionID));
}
cs.close();
cluster.close();
}

上述测试总是失败,总是在一些随机迭代。谁能解释为什么有时更新丢失?



我在本地运行Cassandra,单节点。在osx上使用brew安装。






堆栈跟踪

  java.lang.AssertionError:failed ith time = 4 
预期:fd2fb850-b3ad-4bfb-8971-485c4df097dc
but:was null
在org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
在in.folks.blaze.service.CassandraTest.testWriteUpdateRead(CassandraTest.java:41)
在sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit .runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:50)
在org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
在org.junit。 runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
在org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
在org.junit.internal。 runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit .runners.ParentRunner.access $ 000(ParentRunner.java:58)
at org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run (ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native方法)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain .main(AppMain.java:134)






其他信息:

  Cassandra版本:[cqlsh 5.0.1 | Cassandra 2.1.2 | CQL spec 3.2.0 |本地协议v3] 
Java版本1.8.0_25
Java(TM)SE运行时环境(版本1.8.0_25-b17)
Java HotSpot™64位服务器VM 25.25-b02,混合模式)

< dependency>
< groupId> com.datastax.cassandra< / groupId>
< artifactId> cassandra-driver-core< / artifactId>
< version> 2.1.4< / version>
< / dependency>
< dependency>
< groupId> com.datastax.cassandra< / groupId>
< artifactId> cassandra-driver-mapping< / artifactId>
< version> 2.1.4< / version>
< / dependency>

< dependency>
< groupId> junit< / groupId>
< artifactId> junit< / artifactId>
< version> 4.12< / version>
< scope> test< / scope>
< / dependency>
< dependency>
< groupId> org.mockito< / groupId>
< artifactId> mockito-all< / artifactId>
< version> 1.10.17< / version>
< scope> test< / scope>
< / dependency>
< dependency>
< groupId> org.hamcrest< / groupId>
< artifactId> hamcrest-all< / artifactId>
< version> 1.3< / version>
< scope> test< / scope>
< / dependency>


解决方案

这似乎是一个问题,在它创建后。如果你在第二次更新后等待一小段时间,你会得到正确的值,这似乎是一个问题,但也许只有在本地运行cassandra时才会显着。



我怀疑这是一个cassandra问题,虽然它似乎目前解决在trunk和cassandra-2.1分支。我可以复制1.2.19,2.0.11和2.1.2,但我不能对中继线或cassandra-2.1。我不能根据更改日志查找确切的更改。



编辑2014年1月5日:对用户列表的评论有更多的解释可能是什么发生:。显然,当写入的时间戳完全相同时,会发生这种情况。


@Test
public void testWriteUpdateRead() throws Exception {
  Cluster cluster = Cluster.builder()
      .addContactPoint("127.0.0.1")
      .build();
  Session cs = cluster.connect();
  cs.execute("DROP KEYSPACE if exists readtest;");
  cs.execute("CREATE KEYSPACE readtest WITH replication " +
      "= {'class':'SimpleStrategy', 'replication_factor':1};");
  cs.execute("create table readtest.sessions(" +
      "id text primary key," +
      "passwordHash text," +
      ");");

  for (int i = 0; i < 1000; i++) {
    String sessionID = UUID.randomUUID().toString();
    cs.execute("insert into readtest.sessions (id, passwordHash) values('" + sessionID + "', null)");
    cs.execute("update readtest.sessions set passwordHash='" + sessionID + "' where id = '" + sessionID + "' ");
    ResultSet rs = cs.execute("select * from readtest.sessions where id = '" + sessionID + "'");
    Row row = rs.one();
    assertThat("failed ith time=" + i, row.getString("passwordHash"), equalTo(sessionID));
  }
  cs.close();
  cluster.close();
}

The above test always fails, and always on some random iteration. Can anyone explain why sometimes the update is lost?

I am running Cassandra locally, single node. Installed using brew on osx.


Stack Trace:

java.lang.AssertionError: failed ith time=4
Expected: "fd2fb850-b3ad-4bfb-8971-485c4df097dc"
     but: was null
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at in.folks.blaze.service.CassandraTest.testWriteUpdateRead(CassandraTest.java:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)


Other info:

Cassandra version: [cqlsh 5.0.1 | Cassandra 2.1.2 | CQL spec 3.2.0 | Native protocol v3]
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

<dependency>
  <groupId>com.datastax.cassandra</groupId>
  <artifactId>cassandra-driver-core</artifactId>
  <version>2.1.4</version>
</dependency>
<dependency>
  <groupId>com.datastax.cassandra</groupId>
  <artifactId>cassandra-driver-mapping</artifactId>
  <version>2.1.4</version>
</dependency>

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-all</artifactId>
  <version>1.10.17</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.hamcrest</groupId>
  <artifactId>hamcrest-all</artifactId>
  <version>1.3</version>
  <scope>test</scope>
</dependency>
解决方案

This appears to be an issue where a row is updated right after it's created. If you were to wait a small period of time after the second update, you would get the correct value, that does seem to be an issue, but perhaps only noticeable when running cassandra locally.

I suspect this is a cassandra issue, though it seems to be currently resolved on trunk and cassandra-2.1 branches. I can reproduce against 1.2.19, 2.0.11, and 2.1.2, but I cannot reproduce against trunk or cassandra-2.1. I can't seem to pinpoint the exact change based on the changelog.

EDIT Jan 5 2014: A comment on the user list has more explanation for what is likely to be happening: https://groups.google.com/a/lists.datastax.com/forum/#!topic/java-driver-user/0IDCz96lAeA. Apparently this happens when the timestamps of the writes are exactly the same.

这篇关于Cassandra:将列设置为null后写入将随机丢失。这是一个错误,还是我做错了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-01 19:52