【问题标题】:How to ensure data is eventually written to two Azure blobs?如何确保数据最终写入两个 Azure blob?
【发布时间】:2017-03-05 11:06:39
【问题描述】:

我正在设计一个多租户 Azure Service Fabric 应用程序,我们将在其中将事件数据存储在 Azure Append-Only Blob 中。

会有两种 blob; 合并 blobs(每个租户一个);和 instance blobs(租户拥有的每个“对象”一个 - 每个租户将有 100K+ 个)

每个实例 blob 将有一个写入器。该写入器跟踪上次写入的 blob 位置,从而可以确保(使用条件写入)自上次成功写入以来没有其他写入器写入该 blob。这是我们将用来为每个实例提供强一致性的一个重要方面。

但是,所有对instance blob的写入必须最终(但尽快)到达单个(每个租户)合并blob。

在正常操作下,我希望这些合并写入发生在 ~100 毫秒内。

我的问题是我们应该如何最好地实现这种有保证的双写功能:

实现必须保证写入实例 blob 的数据最终也将写入相应的合并 blob恰好一次

必须避免以下不一致:

  1. 数据已成功写入instance blob,但从未写入相应的merge blob

  2. 数据被多次写入merge blob

【问题讨论】:

    标签: algorithm azure-storage azure-blob-storage distributed-computing azure-service-fabric


    【解决方案1】:

    对我来说最简单的方法是使用事件:服务总线或事件中心或任何其他提供者来保证事件将被存储并且至少在某个地方是可访问的。此外,它还可以将事件批量写入 Blob 存储。此外,我认为它将显着减轻 Service Fabric 的压力,并允许在所需的时间处理事件。
    因此,您可以拥有许多无状态服务或只有 Web Worker,它们将从队列中获取新消息并将它们批量发送到有状态服务。
    假设这将是一个合并服务。您需要对这些服务进行分区,发送按一个分区分组的一批事件的最佳方法是制作此类无状态服务或 Web Worker。

    您可以为每个对象拥有一个单独的 Statefull Actor。但在你的位置上,我会尝试创建 10 万个演员或任何其他实际工作量,看看它会有多昂贵。如果它太贵而且你买不起这样的机器,那么一切都可以在另一个分区的无状态服务中处理。

    好的,现在我们有了下一个方案:将日志放入 ESB,从 ESB 批量或非常频繁地使这些事件达到峰值,处理事务和处理错误。之后,某个队列中的一系列事件达到峰值,它将其发送到特定的合并服务,该服务将数据存储在其状态中并调用特定的参与者来做同样的事情。

    一旦参与者将其数据写入其状态并且服务也这样做,那么 ESB 中的此类 sevent 可以被标记为已处理并从队列中删除。然后,您只需偶尔将存储的数据从 Merge 服务和 Actor 写入 Blob 存储。

    如果 actor 无法存储事件,则操作未完成,Merge 服务也不应该存储数据。如果演员或合并服务无法访问 Blob 存储,则它将在未来变得可访问,并且日志将在保存状态时存储,或者至少可以手动从演员/服务中检索它们。

    如果无法访问 Merge 服务,我会将此类事件存储在 poison message queue 中以供以后处理,或者尝试将日志直接写入 Blob 存储,但这有点危险,尽管此时只能写入一种存储空间非常低。

    【讨论】:

      【解决方案2】:

      您可以为此使用有状态的 Actor。您无需担心并发性,因为没有。在 Actor 的状态下,您可以跟踪哪些操作已成功完成。 (写1,写2)

      不过,在分布式系统中“只写一次”(没有 DTC)永远不会 100% 防水。

      更多信息:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-11-15
        • 1970-01-01
        • 1970-01-01
        • 2021-07-01
        • 2020-11-07
        • 1970-01-01
        • 2013-01-07
        相关资源
        最近更新 更多