gpt4 book ai didi

azure - TTL 删除项目后,COSMOS DB 唯一索引约束冲突

转载 作者:行者123 更新时间:2023-12-03 07:04:07 24 4
gpt4 key购买 nike

我正在使用 azure-spring-boot-starter-cosmos 创建分布式锁库

我的库有两种方法:public void lockResource(String resourceUniqueIdentifier) 和
公共(public)无效unlockResource(字符串资源唯一标识符)

lockResource()方法将接收我想要锁定的资源的resourceUniqueIdentifier,创建一个 Lock() 实例并将其保存在数据库中。

如果锁已经存在(通过将/appName 设置为分区键,将/lockedResourceId 设置为 azure 门户中的唯一键),lockRepository.save() 方法将抛出带有 409 状态代码的异常(因为已经存在冲突)具有相同分区键和唯一键的实体)

因此,为了获取锁,之前获取锁的人需要调用unlockResource(String resourceUniqueIdentifier),或者资源上的 ttl 需要过期(我还在 Lock dto 上设置了一个 ttl 字段,并在 azure 门户)

我的逻辑将尝试使用 while(!isNewLock(lock) && isNotMaximumRetries(retries, resourceUniqueIdentifier)) 获取锁。完整代码如下

Cosmos Config:具有“ session ”一致性级别的直接模式

问题:即使由于 TTL EXPIRATION(假设某个其他服务/线程之前获取了它)而从数据库中删除了某个资源的锁,当尝试再次获取锁时,它仍然会抛出状态码为 409 的 CosmosAccessException。 (“违反唯一索引约束”)。对我来说,虽然锁已从数据库中删除(自从我检查以来),但它仍然在某处保留了一些有关该锁的剩余信息。

LOCK DTO(我没有添加 getter 和 setter):

@Container(containerName = "distributed-lock", timeToLive = -1, autoCreateContainer = false)

公共(public)类锁{

@Id
@GeneratedValue
private String id;

private String lockedResourceId;

@PartitionKey
private String appName;

private Integer ttl;

private long time;

public Lock(String id, String lockedResourceId, String appName, Integer ttl, long time) {
this.id = id;
this.lockedResourceId = lockedResourceId;
this.appName = appName;
this.ttl = ttl;
this.time = time; //todo remove
}

}

锁定服务:

 public void lockResource(String resourceUniqueIdentifier) {
var retries = 0;
var lock = new Lock(UUID.randomUUID().toString(), resourceUniqueIdentifier, appName, lockProperties.getTtl(), Instant.now().toEpochMilli());

while(!isNewLock(lock) && isNotMaximumRetries(retries, resourceUniqueIdentifier)) {
logger.info(I9001.getMessage(), lock.getLockedResourceId(), retries);
waitToUnlock();
retries++;
}
}




private void waitToUnlock() {
try {
Thread.sleep(lockProperties.getRetryInterval());
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted exception while waiting to retry lock", e);
}
}



private boolean isNewLock(Lock lockResource) {
try {
lockResource.setId(UUID.randomUUID().toString());
var lock = lockRepository.save(lockResource);
logger.info(LoggingUtil.X900.getMessage(), lock.getId());
logger.info("SAVED LOCK WITH ID: {}", lock.getId());
var sameLock = lockRepository.getByLockedResourceIdAndAppName(lockResource.getLockedResourceId(), lockResource.getAppName());
logger.info("TESTED SAVED LOCK WITH ID: {}, UniqueId: {}", sameLock.getId(), sameLock.getLockedResourceId());

return true;
} catch (CosmosAccessException cosmosAccessException) {
if (cosmosAccessException.getCosmosException().getStatusCode() == CONFLICT_STATUS_CODE) {
lockResource.setTime(Instant.now().toEpochMilli());
logger.info(LoggingUtil.X900.getMessage(), lockResource.getLockedResourceId(), lockResource.getId());
var alreadyExisting = lockRepository.getByLockedResourceIdAndAppName(lockResource.getLockedResourceId(), lockResource.getAppName());
logger.info("Retrieved duplicate with resId {} and id {}", alreadyExisting, alreadyExisting);

return false;
}
else throw cosmosAccessException;
}
}

最佳答案

问题在于,当资源的离开时间到期时,Cosmos 只会进行部分删除。如果有人调用该资源,由于 ttl 过期,该资源将不会返回。但是,如果您想要在一段时间后保存相同的资源(在容器上设置了一些约束,例如 uniqueKey 和 PartitionKey),您可能会收到 409 状态代码,因为数据将被完全删除当有足够的 RU(资源单位)可用时。

https://learn.microsoft.com/bs-latn-ba/azure/cosmos-db/sql/time-to-live?view=sql-server-ver15

关于azure - TTL 删除项目后,COSMOS DB 唯一索引约束冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71738272/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com