【问题标题】:state manager parallel transactions in runasyncrunasync 中的状态管理器并行事务
【发布时间】:2019-03-14 18:19:00
【问题描述】:

在服务结构有状态服务中,有 RunAsync(cancellationToken) 和 using() 用于状态管理器事务。

我要重构的遗留代码包含两个队列,在 while(true) 内尝试出队,延迟时间为 1 秒。我想摆脱这种不必要的延迟,而是使用两个不同的反应队列(具有可靠队列的信号量)。

问题是,现在需要将依赖于这两个队列的两个不同的工作流分成两个单独的线程,因为如果这两个队列在单个线程中运行,一个 wait() 将阻止其他代码运行。 (我知道最好的做法可能是将这两个任务分成两个微服务,下一个项目。)

我想出了以下代码作为解决方案:

    protected override async Task RunAsync(CancellationToken cancellationToken)
    {
        await Task.WhenAll(AsyncTask1(cancellationToken), AsyncTask2(cancellationToken)).ConfigureAwait(false);
    }

每个任务都包含以下内容:

    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();

        using (var tx = this.StateManager.CreateTransaction())
        {
            var maybeMessage = await messageQueue.TryDequeueAsync(tx, cancellationToken).ConfigureAwait(false);

            if (maybeMessage.HasValue)
            {
                DoWork();
            }

            await tx.CommitAsync().ConfigureAwait(false);
        }
    }

似乎有效,但我只想确定 using(statemanger.createTansaction()) 是否可以以这种并行方式使用..

【问题讨论】:

    标签: service-fabric-stateful azure-service-fabric service-fabric-stateless


    【解决方案1】:

    根据documentation

    根据单项操作的副本角色(如TryDequeueAsync),ITransaction 使用可重复读取隔离级别(当primary时)或快照隔离级别(当**次要时)。


    可重复阅读

    默认情况下,任何可重复读取操作都采用共享锁。

    快照

    使用快照隔离完成的任何读取操作都是无锁的。


    所以如果DoWork 不修改可靠集合,那么多个事务可以并行执行而没有问题。

    在多次读取/更新的情况下 - 这可能会导致死锁,应小心操作。

    【讨论】:

    • 在有状态服务的secondary的情况下,我的理解是他们不参与实际操作,所以我猜上面的语句意味着以Snapshot方式将可靠集合同步到Secondary。
    • @JP_medevice 当您在主副本上执行AddAsync 之类的操作时,它会将序列化数据发送到所有辅助副本。这样做是为了确保在提交ITransaction 时所有辅助副本都具有相同的数据(有关详细信息,请参阅this)。此处的快照隔离意味着在您开始读取操作后,您将看不到主副本提交的任何更改。这些更改将仅在新事务中可用。
    • 这也是我的理解,任何基于队列状态的执行处理仅在初级中完成,我对此逻辑所做的一项谨慎检查是仅基于入队请求将信号量应用于释放队列到可靠队列,只有在单个节点上工作的可靠队列的信号量才有意义,而不是在多个节点上。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 2016-03-16
    • 2012-03-03
    • 1970-01-01
    • 2016-06-29
    相关资源
    最近更新 更多