Azure 如何处理;指定的资源不存在";使用实体组事务清除WADLogs表时出现异常

Azure 如何处理;指定的资源不存在";使用实体组事务清除WADLogs表时出现异常,azure,azure-storage,azure-table-storage,Azure,Azure Storage,Azure Table Storage,我们需要定期清除Azure WADLogs表。我们通过使用实体组事务删除超过15天的记录来实现这一点。逻辑是这样的 bool recordDoesNotExistExceptionOccured = false; CloudTable wadLogsTable = tableClient.GetTableReference(WADLogsTableName); partitionKey = "0" + DateTime.UtcNow.AddDays(noOfDays).Ticks; Table

我们需要定期清除Azure WADLogs表。我们通过使用实体组事务删除超过15天的记录来实现这一点。逻辑是这样的

bool recordDoesNotExistExceptionOccured = false;
CloudTable wadLogsTable = tableClient.GetTableReference(WADLogsTableName);

partitionKey = "0" + DateTime.UtcNow.AddDays(noOfDays).Ticks;
TableQuery<WadLogsEntity> buildQuery = new TableQuery<WadLogsEntity>().Where(
                            TableQuery.GenerateFilterCondition("PartitionKey",                
                            QueryComparisons.LessThanOrEqual, partitionKey));

while (!recordDoesNotExistExceptionOccured)
{
    IEnumerable<WadLogsEntity> result = wadLogsTable.ExecuteQuery(buildQuery).Take(1000);

    //// Batch entity delete.
    if (result != null && result.Count() > 0)
    {
         Dictionary<string, TableBatchOperation> batches = new Dictionary<string, TableBatchOperation>();
         foreach (var entity in result)
         {
             TableOperation tableOperation = TableOperation.Delete(entity);

             if (!batches.ContainsKey(entity.PartitionKey))
             {
                 batches.Add(entity.PartitionKey, new TableBatchOperation());
             }

             // A Batch Operation allows a maximum 100 entities in the batch which must share the same PartitionKey.                        
             if (batches[entity.PartitionKey].Count < 100)
             {
                 batches[entity.PartitionKey].Add(tableOperation);
             }
        }

        // Execute batches.
        foreach (var batch in batches.Values)
        {
            try
            {
                await wadLogsTable.ExecuteBatchAsync(batch);
            }
            catch (Exception exception)
            {
                // Log exception here.

                // Set flag.
                if (exception.Message.Contains(ResourceDoesNotExist))
                {
                    recordDoesNotExistExceptionOccured = true;
                }
                break;
            }
        }
    }
    else
    {                            
        break;
    }
}
bool recordDoesNotExistExceptionOccured=false;
CloudTable wadLogsTable=tableClient.GetTableReference(WADLogsTableName);
partitionKey=“0”+DateTime.UtcNow.AddDays(noOfDays).Ticks;
TableQuery buildQuery=新建TableQuery()。其中(
TableQuery.GenerateFilterCondition(“PartitionKey”,
QueryComparisons.LessThanOrEqual,partitionKey));
而(!RecordDoesNotExistException发生)
{
IEnumerable result=wadLogsTable.ExecuteQuery(buildQuery).Take(1000);
////批处理实体删除。
if(result!=null&&result.Count()>0)
{
字典批处理=新建字典();
foreach(结果中的var实体)
{
TableOperation TableOperation=TableOperation.Delete(实体);
如果(!batches.ContainsKey(entity.PartitionKey))
{
batches.Add(entity.PartitionKey,new TableBatchOperation());
}
//批处理操作允许批处理中最多有100个实体共享同一分区密钥。
if(批处理[entity.PartitionKey].Count<100)
{
批次[entity.PartitionKey].Add(tableOperation);
}
}
//执行批处理。
foreach(批处理中的var批处理。值)
{
尝试
{
等待wadLogsTable.ExecuteBatchAsync(批处理);
}
捕获(异常)
{
//这里记录异常。
//设置标志。
if(exception.Message.Contains(ResourceDoesNotExist))
{
recordDoesNotExistExceptionOccured=true;
}
打破
}
}
}
其他的
{                            
打破
}
}
我的问题是:

  • 这是清除WADLogs表的有效方法吗?如果没有,有什么可以让这更好
  • 这是处理“指定资源不存在异常”的正确方法吗?如果没有,我如何才能使这更好
  • 这种逻辑在任何特定情况下都会失败吗
  • 如果此代码位于部署了多个实例的worker中,该方法将如何更改
  • 我通过引用给出的解决方案,得出了这段代码

  • 如果不能删除整张表,那么批处理通常是清除部分表的最佳方法。然而,上面代码中的细节有几个问题,我将在下面概述

  • 我不确定为什么查询中刚返回的表实体会出现此错误,除非您在另一个线程上从此表中删除内容。但是,在您给出的场景中,当出现错误时,您应该而不是停止整个过程。假设您有1000个结果要删除。第二个已被另一个线程删除,当您再次尝试删除它时返回错误-现在您缺少删除所有其他实体,包括该批中的其他实体,因为批是原子的!为了修复这种情况,我建议从批处理中删除失败的实体(错误消息将包括其索引),重试该批处理,然后继续删除其余批处理

  • 见第2条。此外,如果有100多个实体具有相同的分区键,则不会立即删除其余的实体,而是忽略它们并在下一个循环迭代中删除它们。如果有许多条目具有相同的分区键,这可能会导致大量额外的查询,因此将它们添加到新批中可能更有效

  • 一旦有更多的工人开始工作,那么在当前的设计中,2中的问题将变得更加严重,因为您总是查询前1000个。现在,您将有多个线程下载相同的结果并尝试删除相同的内容。对于当前的设计,这将导致许多错误,因为工作人员将删除相同的结果。我所看到的最简单的解决方案是找到一种更好的方法来划分工作,而不会造成重叠。一个想法可能是让每个工作人员花不同的一天来删除,这还可以优化必须发送的批次数量。当然,还有许多其他有效的策略


  • 如果您将实际代码放在问题中而不是屏幕截图中,这会有所帮助。通过这种方式复制/粘贴变得更容易:P.@Gaurav:我避免了代码,因为它删除了缩进:)。这需要时间,但我已经用代码替换了图像。谢谢,谢谢你回答艾米丽。我同意你的建议。唯一的问题是,在第3点,如果有100多个条目具有相同的分区键,那么由于代码处于while循环中,查询将返回其余条目,这些条目最终将以100个为一批删除。此外,在例外情况下,索引始终为0。因此,我猜测在多个实例的情况下会发生这种情况。我想我必须有一个策略来避免这个场景中的重叠。我刚刚验证过,即使只有一个worker实例,也会发生异常。我猜出现这种异常是因为部署角色时,没有超过15天的记录。有什么方法可以避免这个异常吗?我认为忽略这个异常很好。对于#3,我应该澄清,这样做会更有效,以避免重新查询相同的内容,但正如您所说,在当前的设计中,这不是一个问题。我将编辑我的回复以反映这一点。关于#2,我相信