我们一直在测试集群中遇到问题。
Cassandra配置:
我们遇到问题的表配置:
CREATE TABLE "STATISTICS" (
key timeuuid,
column1 blob,
column2 blob,
column3 blob,
column4 blob,
value blob,
PRIMARY KEY (key, column1, column2, column3, column4)
) WITH COMPACT STORAGE
AND CLUSTERING ORDER BY (column1 ASC, column2 ASC, column3 ASC, column4 ASC)
AND caching = {
'keys':'ALL', 'rows_per_partition':'100'
}
AND compaction = {
'class': 'org.apache.cassandra.db.compaction.LeveledCompactionStrategy'
};
我们的Java代码详细信息
那么,发生了什么事
在高负载下,我们的应用程序在所有节点的cassandra表中执行了许多插入操作。 在此期间,我们只有一个工作流程,接下来我们要对 STATISTICS 表中的一个行进行操作:
在最后一步(4)中,当我们读取所有列时,我们确定已完成所有列的插入(这由我们进行的其他检查保证)
问题在于,有时(在100'000上为2-5次)在stpp 4读取所有列时,我们得到的是4列而不是5列,也就是说,我们丢失了在步骤2中插入的列或3。
我们甚至开始每100毫秒循环读取一次此列,但未获得预期的结果。在这段时间内,我们还使用 cqlsh 检查列-相同的结果,即 4 而不是 5 。
但是,如果我们在此行中添加任何新列,那么我们将立即获得预期的结果,即,我们将从工作流中获得 6 列- 5 列假。 因此,在插入虚拟列之后,我们会丢失在第2步或第3步插入的列。
此外,当我们得到缺少的时间戳(然后是经过评估的列)时,它与从应用节点实际添加此列的时间非常接近。
基本上从app-node-2和app-node-3插入几乎是同时完成的,所以即使我们在第一次读取后的1分钟内插入了虚拟列,最终这两列的时间戳也几乎相同步骤4中的所有列。
使用复制因子3,我们无法重现此问题。
所以开放的问题是:
更新1:
下一个代码用于插入列:
UUID uuid = <some uuid>;
short shortV = <some short>;
int intVal = <some int>;
String strVal = <some string>;
ColumnFamily<UUID, Composite> statisticsCF = ColumnFamily.newColumnFamily(
"STATISTICS",
UUIDSerializer.get(),
CompositeSerializer.get()
);
MutationBatch mb = keyspace.prepareMutationBatch();
ColumnListMutation<Composite> clm = mb.withRow(statisticsCF, uuid);
clm.putColumn(new Composite(shortV, intVal, strVal, null), true);
mb.execute();
更新2:
继续进行测试/调查。
再次遇到这种情况时,我们立即停止(杀死)了我们的Java应用程序。然后可以在 cqlsh 中不断看到特定行不包含插入的列。
要显示它,首先我们在每个cassandra节点上尝试使用nodetool flash:
pssh -h cnodes.txt /path-to-cassandra/bin/nodetool flush
结果-相同,没有出现列。
然后我们重新启动 cassandra群集和列出现了
更新3:
试图通过将 row_cache_size_in_mb 属性设置为 0 (在2Gb之前)来禁用cassandra缓存
row_cache_size_in_mb: 0
之后,问题就消失了。
所以问题可能在OHCProvider中,它被用作默认的缓存提供程序。