【问题标题】:Acquire lease on the same azure blob at the same time同时获取同一个 azure blob 的租约
【发布时间】:2022-04-04 18:13:03
【问题描述】:

在我的团队的应用程序中注意到以下行为:

多个线程尝试使用以下行在同一个 blob 上获取租约:

await blob.AcquireLeaseAsync(TimeSpan.FromSeconds(lockTime), null, null, new BlobRequestOptions() { RetryPolicy = RetryPolicy }, null);

多个线程成功获得租约,每个线程都获得不同的租约,大约在同一时间。 这是因为 AcquireLeaseAsync 是 NOT thread-safe 对吗? 我认为租约是一个锁,所以一次只能授予一个线程?

我们尝试添加租约 ID 为空的访问条件,这似乎很有帮助。

await blob.AcquireLeaseAsync(TimeSpan.FromSeconds(lockTime), null, new AccessCondition { LeaseId = null}, new BlobRequestOptions() { RetryPolicy = RetryPolicy }, null);

但不确定它是否是万无一失的,即在尝试获取 blob 的租约时,是否有多个线程可以通过此访问条件?

以下是我用来生成此问题的代码:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("started");
        var storageConnStr = "";
        var client = CloudStorageAccount.Parse(storageConnStr).CreateCloudBlobClient();
        var container = client.GetContainerReference("test");
        var blob = container.GetBlobReference("Program.cs");
        List<Task> list = new List<Task>();

        for (int i = 0; i < 100; i++)
        {
            list.Add(Task.Run(() => AcquireLease(blob)));
        }
        Task.WhenAll(list).Wait();

    }
    static void AcquireLease(CloudBlob blob)
    {
        try
        {
            var id = blob.AcquireLeaseAsync(TimeSpan.FromSeconds(30), null, null, null, null).Result;
            Console.WriteLine($"Successfully acquired lease on thread {Thread.CurrentThread.ManagedThreadId}, lease id {id}, time is {DateTime.UtcNow}");
        }
        catch (Exception)
        {
            Console.WriteLine($"Got exception at {Thread.CurrentThread.ManagedThreadId}");
        }
    }
}

示例输出:

在线程 86 上成功获取租约,租约 id dfbd393e-46e2-49dc-98f4-853356fbc255,时间是 11/10/2018 2:16:57 AM

在线程 22 上成功获取租约,租约 id f81b3dbf-68f6-401d-b82e-a1c19fb3527c,时间是 11/10/2018 2:16:57 AM

在线程 54 上成功获取租约,租约 id 6c05c2ee-c5a5-4d4e-83a9-b65688fca6df,时间是 11/10/2018 2:16:57 AM

【问题讨论】:

  • 我认为问题在于您正在触发异步操作但没有等待其响应。我敢肯定,如果你等待它,你会得到一个无法获取租约的异常。
  • @GauravMantri 感谢您的回复。如果您查看我使用的代码,我想我确实在等待异步操作完成。
  • blob.AcquireLeaseAsync(TimeSpan.FromSeconds(30), null, null, null, null).Result;
  • 也不清楚为什么AcquireLeaseAsync要依赖客户代码来实现原子租赁?
  • 你能解决这个问题吗?

标签: c# multithreading azure azure-blob-storage


【解决方案1】:

var id = blob.AcquireLeaseAsync 更改为var id = await blob.AcquireLeaseAsync

【讨论】:

    【解决方案2】:

    我不确定这是否是 Azure 存储后端中的错误,但租赁似乎不是原子的。

    应该解决这个问题的一个未记录的解决方案是强制租赁是原子的(它至少在我们的内部测试中有效):

    await blob.AcquireLeaseAsync(
        TimeSpan.FromSeconds(30),
        new RequestConditions { IfNoneMatch = ETag.All } // force atomic
    );
    

    【讨论】:

      猜你喜欢
      • 2020-03-21
      • 2021-06-19
      • 1970-01-01
      • 1970-01-01
      • 2018-12-14
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      • 2022-09-28
      相关资源
      最近更新 更多