使用 datastax java 驱动程序 4.10.0 在 Cassandra 上创建架构时重试查询时出现列族 ID 不匹配异常
Getting around Column family ID mismatch Exception when I retry the query while creating schema on Cassandra using datastax java driver 4.10.0
我编写了一段代码,当我的应用程序出现时,它会使用模式文件自动创建模式。有时在执行查询时我会得到一个 OperationTimedOutException 并且我已经为相同的地方编写了一个重试机制,如果我得到一个 OperationTimedOutException 我会重试查询。
现在,在使用多主机集群时,我的应用程序在创建新 table 时遇到了 OperationTimedOutException,并且代码重试了成功创建架构的查询,但在那之后我 org.apache.cassandra.exceptions.ConfigurationException: Column family ID mismatch
在做了一些研究后,我推测尽管我得到了一个 OperationTimedOutException 请求仍然在一个节点上的 Cassandra 中排队并且我的重试代码发送了另一个请求,该请求可能已经落在了不同的节点和这两个节点上使用不同的列族 ID 创建了他们的 table 版本,并且在架构传播时遇到不匹配。
Post 在创建 table 的情况下,我停止重试查询,而是继续获取键空间元数据并检查是否已创建 table。
try{
execute(cql);
}
catch (QueryOperationTimedOutExcetpion e) {
if (isKeyspaceCreationStatement) {
boolean createdServerSide = false;
while (!createdServerSide) {
ThreadUtils.sleep(TimeUnit.SECONDS.toMillis(5000));
KeyspaceMetadata keyspaceMetadata = getValueFromOptional(sessionToUse.getMetadata().getKeyspace(keyspace));
String cleanedKeyspaceExport = keyspaceMetadata.describeWithChildren(false).toLowerCase().replaceAll("\n", "");
}
这工作了一段时间,然后我将我的 datastax 驱动程序从 3.1.3
升级到 4.10.0
,这删除了 OperationTimedOutException 并引入了 DriverTimeoutException,如果客户端没有从服务器。
但是 post 这次升级我卡在了上面提到的代码上,因为 table 永远不会被创建。据我了解,当客户端没有从服务器获得响应时,DriverTimeoutException 和 OperationTimedOutException 都会返回,但是为什么 table 永远不会被创建。在这个问题之前我应该怎么做?
编程模式创建在分布式系统(例如 Cassandra)中可能很危险。您看到的是所谓的“Schema 分歧”,并且需要documentation 中所述的管理干预。发生这种情况是因为 creation/deletion of keyspaces/tables/... 的代码被发送到一个节点,然后传播到其他节点 - 与“正常”操作相反,它不遵守一致性级别等 - 这是完全不同的机制。
为避免架构不一致,您需要:
- 如果您发送多个 DDL 语句,它们都需要发送到同一个节点,以避免将下一个语句发送到另一个可能尚未更新架构的节点。
- 您需要等到集群中的所有节点都同意模式 - 这应该在发送下一个 DDL 或执行数据操作之前完成。这是通过检查 DDL 执行结果的
getExecutionInfo().isSchemaInAgreement()
或通过在会话对象上调用 .checkSchemaAgreement()
(参见 documentation) 来完成的
我编写了一段代码,当我的应用程序出现时,它会使用模式文件自动创建模式。有时在执行查询时我会得到一个 OperationTimedOutException 并且我已经为相同的地方编写了一个重试机制,如果我得到一个 OperationTimedOutException 我会重试查询。
现在,在使用多主机集群时,我的应用程序在创建新 table 时遇到了 OperationTimedOutException,并且代码重试了成功创建架构的查询,但在那之后我 org.apache.cassandra.exceptions.ConfigurationException: Column family ID mismatch
在做了一些研究后,我推测尽管我得到了一个 OperationTimedOutException 请求仍然在一个节点上的 Cassandra 中排队并且我的重试代码发送了另一个请求,该请求可能已经落在了不同的节点和这两个节点上使用不同的列族 ID 创建了他们的 table 版本,并且在架构传播时遇到不匹配。
Post 在创建 table 的情况下,我停止重试查询,而是继续获取键空间元数据并检查是否已创建 table。
try{
execute(cql);
}
catch (QueryOperationTimedOutExcetpion e) {
if (isKeyspaceCreationStatement) {
boolean createdServerSide = false;
while (!createdServerSide) {
ThreadUtils.sleep(TimeUnit.SECONDS.toMillis(5000));
KeyspaceMetadata keyspaceMetadata = getValueFromOptional(sessionToUse.getMetadata().getKeyspace(keyspace));
String cleanedKeyspaceExport = keyspaceMetadata.describeWithChildren(false).toLowerCase().replaceAll("\n", "");
}
这工作了一段时间,然后我将我的 datastax 驱动程序从 3.1.3
升级到 4.10.0
,这删除了 OperationTimedOutException 并引入了 DriverTimeoutException,如果客户端没有从服务器。
但是 post 这次升级我卡在了上面提到的代码上,因为 table 永远不会被创建。据我了解,当客户端没有从服务器获得响应时,DriverTimeoutException 和 OperationTimedOutException 都会返回,但是为什么 table 永远不会被创建。在这个问题之前我应该怎么做?
编程模式创建在分布式系统(例如 Cassandra)中可能很危险。您看到的是所谓的“Schema 分歧”,并且需要documentation 中所述的管理干预。发生这种情况是因为 creation/deletion of keyspaces/tables/... 的代码被发送到一个节点,然后传播到其他节点 - 与“正常”操作相反,它不遵守一致性级别等 - 这是完全不同的机制。
为避免架构不一致,您需要:
- 如果您发送多个 DDL 语句,它们都需要发送到同一个节点,以避免将下一个语句发送到另一个可能尚未更新架构的节点。
- 您需要等到集群中的所有节点都同意模式 - 这应该在发送下一个 DDL 或执行数据操作之前完成。这是通过检查 DDL 执行结果的
getExecutionInfo().isSchemaInAgreement()
或通过在会话对象上调用.checkSchemaAgreement()
(参见 documentation) 来完成的