Java Cassandra更新不一致

Java Cassandra更新不一致,java,cassandra,astyanax,Java,Cassandra,Astyanax,我在本地(mac)计算机和远程unix服务器上运行以下代码: public void deleteValue(final String id, final String value) { log.info("Removing value " + value); final Collection<String> valuesBeforeRemoval = getValues(id); final MutationBatch m = keyspace.prepar

我在本地(mac)计算机和远程unix服务器上运行以下代码:

public void deleteValue(final String id, final String value) {
    log.info("Removing value " + value);
    final Collection<String> valuesBeforeRemoval = getValues(id);
    final MutationBatch m = keyspace.prepareMutationBatch();
    m.withRow(VALUES_CF, id).deleteColumn(value);
    try {
      m.execute();
    } catch (final ConnectionException e) {
      log.error("Unable to delete  location " + value, e);
    }
    final Collection<String> valuesAfterRemoval = getValues(id);
    if (valuesAfterRemoval.size()!=(valuesBeforeRemoval.size()-1)) {
      log.error("value " + value + " was supposed to be removed from list "  + valuesBeforeRemoval + " but it wasn't: " + valuesAfterRemoval);
    }
...
  }

protected Collection<String> getValues(final String id) {
  try {
    final OperationResult<ColumnList<String>> operationResult = keyspace
            .prepareQuery(VALUES_CF).getKey(id).execute();
    final ColumnList<String> result = operationResult.getResult();
    if (result.isEmpty()) {
      log.info("No  value found for id: " + id);
      return new ArrayList<String>();
    }
    return result.getColumnNames();
  } catch (final ConnectionException e) {
    log.error("Unable to retrieve session " + id, e);
  }
  return new ArrayList<String>();
}
但该行是在我的开发服务器上执行的:

[错误][main][n.o.w.s.d.SessionDaoCassandraImpl][2013-03-08 13:12:24801] []-值3应该从列表[3,2,1,0,7,6,5,4,9,8]中删除,但它不是:[3,2,1,0,7,6,5,4,9,8]

  • 我正在使用com.netflix.astyanax
  • 我的本地机器和远程开发服务器都连接到 同样的卡桑德拉案例
  • 我的本地机器和远程开发服务器都运行相同的测试 创建新行族,并在删除一条记录之前添加10条记录
  • 在dev上发生错误时,log.error(“无法删除 位置“+值,e);未执行(即运行删除 命令未生成任何异常)
  • 我100%肯定没有其他代码影响 当我在dev上运行测试时,这不是 奇怪的并发问题
有什么可能解释deleteColumn(value)请求运行时没有产生任何错误,但仍然没有从数据库中删除该列

附加信息

下面是我如何创建键空间的:

create keyspace sessiondata
    with placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy'
    and strategy_options = {replication_factor:1};
下面是我如何创建列族值的方法,在上面的代码中引用为值\u CF:

create column family values
    with comparator = UTF8Type
;
下面是如何定义上述java代码中引用的键空间:

final AstyanaxContext.Builder contextBuilder = getBuilder();
final AstyanaxContext<Keyspace> keyspaceContext = contextBuilder
        .forKeyspace(keyspaceName).buildKeyspace(
                ThriftFamilyFactory.getInstance());
keyspaceContext.start();
keyspace = keyspaceContext.getEntity();
第二次更新

  • 首先,这些问题不仅仅与删除有关。在更新数据库中的记录、读取记录以及无法读取我刚刚编写的更新时,我发现了类似的问题

  • 其次,我创建了一个测试,它执行100次以下操作:

    • 在cassandra中写一行
    • 在cassandra中更新该行
    • 从cassandra处读回该行,检查该行是否确实更新过,如果没有更新,则在延迟后定期再次检查
    我从该测试中观察到:

    • 同样,当我在本地运行代码时,所有100次迭代都会立即通过(不需要重试)
    • 当我在远程服务器上运行该代码时,有些迭代会通过,有些会失败。当它们失败时,无论延迟有多大(我最多等待10秒),测试总是失败
在这一点上,我真的不知道任何cassandra安装程序如何解释这种行为,因为我连接到同一台服务器进行测试,而且我插入的延迟比从本地机器连接时运行测试可能需要的任何额外延迟都要大

唯一相关的区别似乎是代码运行在哪台机器上

第三次更新

如果在上一次更新中提到的测试中,我在两次写入之间插入了一个延迟,那么如果延迟>=1000毫秒,代码开始通过。比如说,100毫秒的延迟没有帮助。我还修改了构建器,将默认读写一致性设置为最严格的:ALL,这对测试结果没有影响(仍然有一半的时间失败,除非写入之间的延迟>1s):


若要调试,请尝试打印整行,而不仅仅是列名。当我说整行时,我指的是列名、列值和时间戳。很可能是你的一台测试机器上的时钟出错,这会把你的测试扔到另一台机器上

另一件需要仔细检查的事情是,在应用程序和cassandra中,ip确实是您所认为的。当您检索它时,在一些东西之间打印它,比如println(“-”+ip“-”)。在执行deleteSecureLocation的try块之前和之后,只对该列执行get,而不是整行。我不太确定如何在astynax中做到这一点,在cli上它将是get[id][ip]


要记住的是,即使没有要删除的内容,删除也不会失败。对cassandra来说,这是一个写操作,唯一能使其成为删除操作的是,如果在读取时,它是针对该行/列名的最新时间戳条目。

您是否意识到墓碑行为,并对此加以防范?我不熟悉astyanax API,但当您执行删除操作时,相关项目将一直出现在结果中,直到Cassandra将其清理干净,您需要仔细查看结果,看看该项目是否确实被删除。嗯,不,我对墓碑行为一无所知,从我读到的内容来看,这可能是原因,尽管这不能很好地解释为什么它发生在我的机器上,而不是一个开发人员身上,除非我连接到cassandra的延迟足够长,如果我在开发人员身上运行,条目有时间消失,而它们没有消失。在任何情况下,我将从您刚才建议的角度更仔细地研究这一点。谢谢。从Cassandra返回的响应中不会显示列删除,只有行删除会显示。所以这是一个你不回读你马上写的东西的例子。Cassandra在使用最终一致性时有这种行为。您使用的复制策略和复制选项是什么?您读写的一致性级别是什么?很可能删除尚未传播,并且您的读取使用了未看到删除的其他节点。也许你从unix设备上的连接速度比你的mac电脑快,所以你只能在那里看到它。据我所知,你们都描述了同样的问题,事实上是正确的:我在读取已删除的数据之前插入了1秒延迟,没有发现任何不一致。你们中至少有一个人想把你们的评论作为答案,让我接受吗?Richard,我正在使用placement_strategy='org.apache.cassandra.locator.SimpleStrategy'和strategy_options={replication_factor:1};现在我可以看到,我可以为我的查询设置一致性级别,以覆盖Astyaniax使用的任何默认值。如果您真的使用复制因子1,这无法解释它,除非您对写入使用一致性级别ANY,而
final AstyanaxContext.Builder contextBuilder = getBuilder();
final AstyanaxContext<Keyspace> keyspaceContext = contextBuilder
        .forKeyspace(keyspaceName).buildKeyspace(
                ThriftFamilyFactory.getInstance());
keyspaceContext.start();
keyspace = keyspaceContext.getEntity();
  private Builder getBuilder() {
    final AstyanaxConfigurationImpl conf = new AstyanaxConfigurationImpl()
    .setDiscoveryType(NodeDiscoveryType.NONE)
    .setRetryPolicy(new RunOnce());

    final ConnectionPoolConfigurationImpl poolConf = new ConnectionPoolConfigurationImpl("MyPool")
    .setPort(port)
    .setMaxConnsPerHost(1)
    .setSeeds(value);

    return new AstyanaxContext.Builder()
    .forCluster(cluster)
    .withAstyanaxConfiguration(conf)
    .withConnectionPoolConfiguration(poolConf)
    .withConnectionPoolMonitor(new CountingConnectionPoolMonitor());
  }
final AstyanaxConfigurationImpl conf = new AstyanaxConfigurationImpl()
.setDiscoveryType(NodeDiscoveryType.NONE)
.setRetryPolicy(new RunOnce()).setDefaultReadConsistencyLevel(ConsistencyLevel.CL_ALL).setDefaultWriteConsistencyLevel(ConsistencyLevel.CL_ALL);