首先,这可能最终成为一个菜鸟问题,但仍然......我试图为这个概念找到一个好的解决方案,但谷歌对我来说不起作用。
我正在使用 Azure Functions 创建导入。将 BLOB 上传到 BLOB 存储容器时会触发函数。该函数读取文件,并在验证队列上传递每个导入条目。验证失败时,实体将传递到失败队列。验证成功后,实体将在成功队列上排队。
另一个函数读取成功队列并开始将实体写入表存储。当该过程失败时,实体将排队到失败队列。
处理和存储失败队列中的实体,以便用户知道出了什么问题,并存储原始导入数据,以便用户可以修复错误。
在我看来,这是使用函数实现导入过程的最佳方式。我知道有很多功能...但它们都有一个单一的责任(例如读取文件、验证等(。
现在我的问题是,当实体成功存储或失败实体成功存储时,我还会向状态队列发送一条消息,告知某个实体的导入是否成功。另一个 Azure 函数处理该状态队列,并使用最新状态更新表存储中的单个条目。导入的状态如下所示:
CorrelationId <-- The import identifier
StartedAt (date time)
TotalEntries (int)
Succeeded (int)
Failed (int)
CompletedAt (date time)
显然,成功或失败的 int 会为队列上的每条消息增加一个。此外,当队列大小增加时,可用区函数实例的数量会增加,并且更多函数开始同时更新表存储条目,从而导致错误。我可以选择使用 ETag,这会导致一些队列条目失败(而且速度很慢!!(,或者我可以将 ETag 设置为 "*",这使得过程更快,但随后我只是错过了数据。你应该如何处理/解决这种情况?
谢谢一堆!
Azure 表存储不是处理此类方案的最佳选择。应在 SQL 数据库或 Cosmos DB 上创建具体化视图,以便更好地处理并发/事务。
作为另一个选项,可以使用事件中心/流分析提供实时统计信息。
不是你问题的答案,但可以把它看作是一些"思考的食粮":)。
您可以做的是创建一个表(我们称之为StatusTracker
(,您将在其中存储每个操作的状态。这将是一个简单的表,其中PartitionKey
作为日期/时间的刻度(或反向刻度(表示(您可以将其设置为分钟粒度,以便将一分钟的数据存储在单个分区中(,RowKey
作为操作的唯一 ID,然后是一个状态属性,告诉您操作是失败还是成功。您可以使用此表向用户提供近乎实时的反馈。由于您始终在此表中插入记录,因此不会遇到并发问题。
然后你可以写另一个函数(哦不...不是另一个将触发计时器的函数:)((例如每 5 分钟运行一次(。它将要做的是查询第一个表(状态跟踪器(,汇总数据并更新您的状态表。由于此表仅由单个函数更新,因此您同样不会遇到并发问题。