StackExchange.Redis - 等待锁的最佳方式
StackExchange.Redis - best way to wait for a lock
我有以下方法等待 Redis 键的独占锁。这种方法有效,但我想知道是否有没有 for 循环和 Thread.Sleep.
的更好方法
/// <summary>
/// wait up to 2 seconds to achieve a lock!
/// The lock is good for a maximum of 3 seconds
/// </summary>
/// <param name="codeID"></param>
internal void WaitForSingleUseLock(CodeID codeID)
{
var key = _redemptionRepo.SingleUseCodeLockPrefix + codeID.Value;
var expiration = TimeSpan.FromSeconds(3);
for (var i = 0; i < 20; i++)
{
var lockAchieved = _cacheRepo.LockTake(key, "1", expiration);
if (lockAchieved)
{
break;
}
Thread.Sleep(TimeSpan.FromMilliseconds(100));
}
}
我唯一可以建议不同的是将 pub/sub 视为侧通道(意思是:另外,而不是替代),用于指示锁 可能 的时间现在可用 - 即在释放时发布,并使用 sub 释放计时器(通过监视器或异步等待句柄)。
除此之外:没有。 Redis 没有挂起队列的概念。您也许 可能 使用列表构建一个,但是...
在考虑了@Marc 的评论并与我的团队会面讨论 Task.Delay()
在这种情况下优于 Thread.Sleep()
的好处后,我决定将此作为最终解决方案:
/// <summary>
/// wait up to 3 seconds to achieve a lock!
/// The lock is good for a maximum of 3 seconds
///
/// Returns the total amount of time until the lock was taken
/// </summary>
internal virtual async Task<TimeSpan> WaitForSingleUseLock(CodeID codeID)
{
var key = _redemptionRepo.SingleUseCodeLockPrefix + codeID.Value;
var totalTime = TimeSpan.Zero;
var maxTime = TimeSpan.FromSeconds(3);
var expiration = TimeSpan.FromSeconds(3);
var sleepTime = TimeSpan.FromMilliseconds(50);
var lockAchieved = false;
while (!lockAchieved && totalTime < maxTime)
{
lockAchieved = _cacheRepo.LockTake(key, "1", expiration);
if (lockAchieved)
{
continue;
}
await Task.Delay(sleepTime);
totalTime += sleepTime;
}
return totalTime;
}
我有以下方法等待 Redis 键的独占锁。这种方法有效,但我想知道是否有没有 for 循环和 Thread.Sleep.
的更好方法 /// <summary>
/// wait up to 2 seconds to achieve a lock!
/// The lock is good for a maximum of 3 seconds
/// </summary>
/// <param name="codeID"></param>
internal void WaitForSingleUseLock(CodeID codeID)
{
var key = _redemptionRepo.SingleUseCodeLockPrefix + codeID.Value;
var expiration = TimeSpan.FromSeconds(3);
for (var i = 0; i < 20; i++)
{
var lockAchieved = _cacheRepo.LockTake(key, "1", expiration);
if (lockAchieved)
{
break;
}
Thread.Sleep(TimeSpan.FromMilliseconds(100));
}
}
我唯一可以建议不同的是将 pub/sub 视为侧通道(意思是:另外,而不是替代),用于指示锁 可能 的时间现在可用 - 即在释放时发布,并使用 sub 释放计时器(通过监视器或异步等待句柄)。
除此之外:没有。 Redis 没有挂起队列的概念。您也许 可能 使用列表构建一个,但是...
在考虑了@Marc 的评论并与我的团队会面讨论 Task.Delay()
在这种情况下优于 Thread.Sleep()
的好处后,我决定将此作为最终解决方案:
/// <summary>
/// wait up to 3 seconds to achieve a lock!
/// The lock is good for a maximum of 3 seconds
///
/// Returns the total amount of time until the lock was taken
/// </summary>
internal virtual async Task<TimeSpan> WaitForSingleUseLock(CodeID codeID)
{
var key = _redemptionRepo.SingleUseCodeLockPrefix + codeID.Value;
var totalTime = TimeSpan.Zero;
var maxTime = TimeSpan.FromSeconds(3);
var expiration = TimeSpan.FromSeconds(3);
var sleepTime = TimeSpan.FromMilliseconds(50);
var lockAchieved = false;
while (!lockAchieved && totalTime < maxTime)
{
lockAchieved = _cacheRepo.LockTake(key, "1", expiration);
if (lockAchieved)
{
continue;
}
await Task.Delay(sleepTime);
totalTime += sleepTime;
}
return totalTime;
}