Java Cassandra更新不一致
我在本地(mac)计算机和远程unix服务器上运行以下代码: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
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上运行测试时,这不是 奇怪的并发问题
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中,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);