我们需要定期清除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;
}
}
我的问题是:
- 这是清除WADLogs表的有效方法吗?如果没有,还有什么能让情况变得更好
- 这是处理"指定资源不存在异常"的正确方法吗?如果没有,我该如何做得更好
- 这种逻辑在任何特定情况下都会失败吗
- 如果此代码位于部署了多个实例的工作程序中,这种方法将如何改变
我参考了这里给出的解决方案,得出了这个代码。
-
如果不能直接删除整个表,那么批处理通常是清除表的一部分的最佳方式。然而,在上面的代码中有一些细节问题,我将在下面概述。
-
我不知道为什么在查询中刚刚返回的表实体中会出现此错误,除非您在另一个线程上从该表中删除内容。但是,在您给出的场景中,当出现错误时,您应该而不是停止整个过程。假设您有1000个结果要删除。第二个已经被另一个线程删除,当你再次尝试删除它时返回了一个错误-现在你错过了删除所有其他实体,包括该批中的其他实体,因为批是原子的!要修复这种情况,我建议从批处理中删除失败的实体(错误消息将包括其索引),重试该批处理,然后继续删除其余批处理。
-
参见2。此外,如果有100多个实体具有相同的分区键,则不会立即删除其余实体,而是忽略它们,并在下一次循环迭代中删除它们。如果有许多条目具有相同的分区键,这可能会导致大量额外的查询,因此将它们添加到新批中可能会更高效。
-
一旦有更多的工作人员参与,2中的问题将在当前设计中变得更糟,因为您总是查询前1000个。现在,您将有多个线程下载相同的结果,并试图删除相同的内容。在当前的设计中,这将导致许多错误,因为工作人员将删除相同的结果。我看到的最简单的解决方案是找到一种更好的方法来划分工作,而不会造成重叠。一个想法可能是让每个工作人员花不同的时间删除,这也会带来优化必须发送的批次数量的额外好处。当然,还有许多其他有效的策略。