代码改变世界

Redis 分布式锁

2020-10-31 22:47  qgbo  阅读(159)  评论(0编辑  收藏  举报

分布式锁 有阻塞和不阻塞的。  阻塞:

using var client = new RedisClient("127.0.0.1", 6379);
using var datalock = client.AcquireLock("DataLock:" + key,timeout)
{.....}
上面是正常的写法. 这样的原理是
client.AcquireLock 这个方法会去拿锁,如果拿到,向下执行。
如果拿不到会,阻塞住当前线程,超时就异常。
using,实际上就是封装了 try catch 的便捷写法。在catch中 执行Dipose();
这样异常之后,下面的业务代码就不再执行了。
client.AcquireLock  调用了 ServiceStack.Common 的一个帮助方法 RetryUntilTrue。 可见这个方法会超时异常, 这个里面还有个睡眠,睡眠时间还会变的。
        public static void RetryUntilTrue(Func<bool> action, TimeSpan? timeOut=null)
        {
            var i = 0;
            var firstAttempt = DateTime.UtcNow;

            while (timeOut == null || DateTime.UtcNow - firstAttempt < timeOut.Value)
            {
                i++;
                if (action())
                {
                    return;
                }
                SleepBackOffMultiplier(i);
            }

            throw new TimeoutException($"Exceeded timeout of {timeOut.Value}");
        }

不阻塞就是 用这个方法 bool isLocked = client.Add<string>("DataLock:" + key, key, timeout);
ADD 会判断这个值存在,存在什么都不操作。不存在就写进去。业务结束,把这个值remove, 下一个线程还能拿到锁。