首页 > 解决方案 > 如何管理 Cosmos DB 中多次写入的会话令牌?

问题描述

我们有一个业务场景,客户端向我们发送请求,然后我们的后端服务同时插入多个文档并返回最新的 CosmosDB 会话令牌。逻辑看起来与此大致相似:

// Controller Code
[HttpPost]
public async Task<IActionResult> Demo([FromBody] User[] users)
{
  // Create multiple documents here
  var tasks = new List<Task>();
  foreach(var user in users)
  {
    tasks.add(this.container.CreateItemAsync(user, new PartitionKey("my partitionKey")));
  }
  
  // task when all returns an array of ItemResponses
  ItemResponse<User> [] usersItemResponses = await Task.WhenAll(tasks); 
  
  // I could extract the session tokens associated with each ItemResponse
  List<string> sessionTokens = usersItemResponses.Select(response => response.Headers.Session)


  // Here I would like to return the newest session token to the client side, but because the tasks were executed in parallel, I wouldn't know which request finished last, and therefore no way to get the latest session token.
  string sessionTokenString;
  return this.Ok(sessionTokenString);
}

但是,我找不到有关如何比较会话令牌的文档,并且我不想按顺序执行这些写入操作。

我们如何比较这些写操作的会话令牌并将最新的会话令牌返回给我们的客户端,以便他们可以在后续请求中读取数据库数据?

标签: azureazure-cosmosdbconsistency

解决方案


您不需要自己比较会话令牌。将请求的响应标头中返回的会话令牌流向最终用户,然后将其传递回请求选项中,以确保用户正在阅读自己的写入。

有关示例,请参阅利用会话令牌

由于评论太短,在此更新。

对于每个用户发送一批写入的场景,您可以自己管理会话令牌并进行比较。会话令牌的格式是

{pkrangeid}:{Version}#{GlobalLSN}#{RegionId1}={LocalLsn1}#{RegionId2}={LocalLsn2}....#{RegionIdN}={LocalLsnN}. 

但是,如果您要手动检查这一点,则基本上是在执行会影响性能的分布式锁。如果您真正需要的是始终获取最新数据,那么您可以使用 Bounded Staleness 一致性。BS 进行 2 个副本读取并为您比较 LSN。如果它们匹配,则数据是最新的,如果它们不匹配,则返回具有更高 LSN 的数据。由于所有写入都针对三个副本,因此您将始终获得最新数据。唯一的缺点是读取是会话一致性的 2 倍,因为它是 2 个副本读取。但是,比您建议的要简单得多。


推荐阅读