runasync 中的状态管理器并行事务

state manager parallel transactions in runasync

在 Service Fabric 有状态服务中,状态管理器事务有 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()) 是否可以以这种并行方式使用..

根据documentation

根据单项操作的副本角色(如 TryDequeueAsync),ITransaction 使用 Repeatable Read 隔离级别(当 primary) 或 Snapshot 隔离级别(当 **secondary)。


可重复读取

Any Repeatable Read operation by default takes Shared locks.

快照

Any read operation done using Snapshot isolation is lock free.


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

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