public void AcquireFromMultipleThreads()
        {
            var db = RedisUtils.CreateClient();

            var sync = new ManualResetEventSlim();

            var thread1 = new Thread(state =>
            {
                using (var testLock1 = RedisLock.Acquire(db, "test", TimeSpan.FromMilliseconds(50)))
                {
                    // ensure nested lock release doesn't release parent lock
                    using (var testLock2 = RedisLock.Acquire(db, "test", TimeSpan.FromMilliseconds(50)))
                    { }

                    sync.Set();
                    Thread.Sleep(200);
                }
            });

            var thread2 = new Thread(state =>
            {
                Assert.True(sync.Wait(1000));

                Assert.Throws <DistributedLockTimeoutException>(() =>
                {
                    using (var testLock2 = RedisLock.Acquire(db, "test", TimeSpan.FromMilliseconds(50)))
                    { }
                });
            });

            thread1.Start();
            thread2.Start();
            thread1.Join();
            thread2.Join();
        }
        public void TwoContendingLocks()
        {
            var db = RedisUtils.CreateClient();

            using (var testLock1 = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(100)))
                Assert.Throws <TimeoutException>(() => new RedisLock(db, "testLock", "otherOwner", TimeSpan.FromMilliseconds(10)));
        }
        private async Task NestedTask(IDatabase db)
        {
            await Task.Yield();

            using (var lestLock2 = RedisLock.Acquire(db, "test", TimeSpan.FromMilliseconds(10)))
                Assert.NotNull(lestLock2);
        }
Exemple #4
0
        public async ValueTask <ILock> GetLock(string key)
        {
            if (_disposed)
            {
                throw new LockException("LockProvider is disposed");
            }

            StartMonitoring();

            var @lock = new RedisLock(key, this);

            //await _db.sScriptEvaluateAsync(_script, new RedisKey[] { new RedisKey(key) });
            var adquired = await _db.LockTakeAsync(key, @lock.Token, _expire);

            if (adquired)
            {
                _logger.LogInformation("Lock on {Key} adquired", @lock.Key);
                @lock.AdquireLock();
                lock (_locks)
                {
                    _locks.Add(@lock);
                }
                return(@lock);
            }

            lock (_locks)
            {
                _locks.Add(@lock);
            }

            _logger.LogInformation("Lock on {Key} pending", @lock.Key);
            return(await @lock.CreateTask());
        }
Exemple #5
0
        /// <summary>
        /// 秒杀方法
        /// </summary>
        public void SkillProduct()
        {
            try
            {
                RedisLock redisLock = new RedisLock();
                redisLock.Lock();
                // 1、获取商品库存
                var stocks = getPorductStocks();

                // 2、判断商品库存是否为空
                if (stocks == 0)
                {
                    // 2.1 秒杀失败消息
                    Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}:不好意思,秒杀已结束,商品编号:{stocks}");
                    redisLock.unLock();
                    return;
                }

                // 3、秒杀成功消息
                Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}:恭喜你,秒杀成功,商品编号:{stocks}");

                // 4、扣减商品库存
                subtracPorductStocks();

                redisLock.unLock();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
        public void GetLock_With_Single_Thread_Test()
        {
            var rl = new RedisLock(rk, rs, defaultExpire); //test logic:expireDate is too small
            var r1 = rl.GetLock();
            var r2 = rl.GetLock();

            Assert.True(r1 && r2);
        }
        public void AcquireAndDisposeLock()
        {
            var db = RedisUtils.CreateClient();

            using (var testLock = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(1)))
                Assert.NotNull(testLock);
            using (var testLock = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(1)))
                Assert.NotNull(testLock);
        }
Exemple #8
0
 public RedSyncLock(RedisContextProvider context, string key, int expiryTimeout = 30000, int waitTimeout = 10000, int retryTimeout = 100)
 {
     if (context == null)
     {
         throw new ArgumentNullException(nameof(context));
     }
     _lock = context.LockFactory.Create(key, TimeSpan.FromMilliseconds(expiryTimeout),
                                        TimeSpan.FromMilliseconds(waitTimeout), TimeSpan.FromMilliseconds(retryTimeout));
 }
        public void AcquireInSequence()
        {
            var db = RedisUtils.CreateClient();

            using (var testLock = RedisLock.Acquire(db, "testLock", TimeSpan.FromMilliseconds(1)))
                Assert.NotNull(testLock);
            using (var testLock = RedisLock.Acquire(db, "testLock", TimeSpan.FromMilliseconds(1)))
                Assert.NotNull(testLock);
        }
Exemple #10
0
        /// <summary>
        /// 演示阻塞锁
        /// </summary>
        /// <param name="redisManager"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        private static async Task ShowBlockingLockAsync(RedisManager redisManager, int index)
        {
            Console.WriteLine($"{index} Start");
            await using RedisLock redisLock = await redisManager.GetBlockingLockAsync("LockKey", 10000);

            await Task.Delay(1000);

            Console.WriteLine($"{index} End");
        }
        public void NestLock()
        {
            var db = RedisUtils.CreateClient();

            using (var testLock1 = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(100)))
            {
                using (var testLock2 = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(100)))
                { }
            }
        }
        public void GetLockAfterAnotherTimeout()
        {
            var db = RedisUtils.CreateClient();

            using (var testLock = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(50)))
            {
                Thread.Sleep(60);
                using (var testLock2 = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(10)))
                    Assert.NotNull(testLock2);
            }
        }
Exemple #13
0
        /// <summary>
        /// 演示阻塞锁
        /// </summary>
        /// <param name="redisManager"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        private static async Task ShowNonBlockingLockAsync(RedisManager redisManager, int index)
        {
            Console.WriteLine($"{index} Start");
            await using RedisLock redisLock = await redisManager.GetNonBlockingLockAsync("LockKey", 10000);

            if (redisLock == null)
            {
                return;
            }
            Console.WriteLine($"{index} End");
        }
        public void ExtendsALock()
        {
            var db = RedisUtils.CreateClient();

            using (var testLock = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(100)))
            {
                Assert.NotNull(testLock);
                using (var testLock2 = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(10)))
                    Assert.NotNull(testLock2);
            }
        }
 public void LockReentry()
 {
     UseDatabase(Database =>
     {
         using (var lock1 = new RedisLock(Redis.Storage.GetDatabase(), "lock", "1", TimeSpan.FromMilliseconds(30)))
         {
             using (var lock2 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(5)))
             {
             }
         }
     });
 }
 public void LockRelease()
 {
     UseDatabase(Database =>
     {
         using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMinutes(1)))
         {
         }
         using (var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMinutes(1)))
         {
         }
     });
 }
Exemple #17
0
        private void Remove(RedisLock @lock)
        {
            if (!_db.LockRelease(@lock.Key, @lock.Token))
            {
                _logger.LogInformation("Lock on {Key} expired or the process doesn't own the lock", @lock.Key);
            }

            lock (_locks)
            {
                _locks.Remove(@lock);
            }
        }
        public void LockReentry()
        {
            UseDatabase(Database =>
            {
                using (var lock1 = new RedisLock(Redis.Storage.GetDatabase(), "lock", "1", TimeSpan.FromMilliseconds(30)))
                {
                    using (var lock2 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(5)))
                    {

                    }
                }
            });
        }
        public async Task AcquireFromNestedTask()
        {
            var db = RedisUtils.CreateClient();

            using (var lock1 = RedisLock.Acquire(db, "test", TimeSpan.FromMilliseconds(50)))
            {
                Assert.NotNull(lock1);

                await Task.Delay(100);

                await Task.Run(() => NestedTask(db));
            }
        }
 public void LockCollision_WithTimeout()
 {
     UseDatabase(Database =>
     {
         using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(30)))
         {
             Assert.Throws <TimeoutException>(() =>
             {
                 var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMilliseconds(1));
             });
         }
     });
 }
 public void LockCollision()
 {
     UseDatabase(Database =>
     {
         using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(30)))
         {
             Thread.Sleep(20); //Sleep to give the wait loop time to run. If not set high enough lock2 will Timeout
             using (var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMilliseconds(30)))
             {
             }
         }
     });
 }
 public void LockCollision_WithTimeout()
 {
     UseDatabase(Database =>
     {
         using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(30)))
         {
             Assert.Throws<TimeoutException>(() =>
             {
                 var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMilliseconds(1));
             });
         }
     });
 }
Exemple #23
0
        public async Task <RedisLock> GetLockAsync()
        {
            using (var redisLock = await _redisLockFactory.CreateAsync(_resource, _expiry))
            {
                _redisLock = redisLock;

                if (redisLock.IsAcquired)
                {
                    Thread.Sleep(_interval);
                }
                return(redisLock);
            }
        }
        public void ReleaseNestedAfterTimeout()
        {
            var db = RedisUtils.CreateClient();

            using (var testLock1 = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(50)))
            {
                using (var testLock2 = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(1)))
                { }

                Thread.Sleep(60);
                using (var testLock2 = new RedisLock(db, "testLock", "otherOwner", TimeSpan.FromMilliseconds(1))) { };
                Assert.True(true);
            }
        }
        public void AcquireNested()
        {
            var db = RedisUtils.CreateClient();

            using (var testLock1 = RedisLock.Acquire(db, "testLock", TimeSpan.FromMilliseconds(100)))
            {
                Assert.NotNull(testLock1);

                using (var testLock2 = RedisLock.Acquire(db, "testLock", TimeSpan.FromMilliseconds(100)))
                {
                    Assert.NotNull(testLock2);
                }
            }
        }
        public void NestLockDisposePreservesRoot()
        {
            var db = RedisUtils.CreateClient();

            using (var testLock1 = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(1000)))
            {
                using (var testLock2 = new RedisLock(db, "testLock", "owner", TimeSpan.FromMilliseconds(1000)))
                { }

                Assert.Throws <TimeoutException>(() =>
                {
                    using (var testLock2 = new RedisLock(db, "testLock", "otherOwner", TimeSpan.FromMilliseconds(1))) { };
                });
            }
        }
        public void LockReentry_DontReleaseEarly()
        {
            UseDatabase(Database =>
            {
                using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(60)))
                {
                    using (var lock3 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(5)))
                    {
                    } //Make sure the lock isn't removed when the nested lock is disposed

                    Assert.Throws <TimeoutException>(() =>
                    {
                        var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMilliseconds(1));
                    });
                }
            });
        }
 public void LockReentry_ExtendLock()
 {
     UseDatabase(Database =>
     {
         using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(10)))
         {
             using (var lock3 = new RedisLock(Database, "lock", "1", TimeSpan.FromMinutes(1)))
             {
             }
             Thread.Sleep(20);
             Assert.Throws <TimeoutException>(() =>
             {
                 var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMilliseconds(1));
             });
         }
     });
 }
Exemple #29
0
        private void Extend(RedisLock @lock)
        {
            var result = _db.LockExtend(@lock.Key, @lock.Token, _expire);

            if (!result)
            {
                _logger.LogInformation("Log on {Key} expired or the process doesn't own the lock", @lock.Key);

                lock (_locks)
                {
                    _locks.Remove(@lock);
                }

                throw new LockException($"Lock {@lock.Key} Expired or the process doesn't own the lock");
            }
            @lock.AdquireLock();
        }
        public void GetLock_With_Multi_Threads_Test()
        {
            int threadCount = 10;
            var rl          = new RedisLock(rk, rs, defaultExpire);
            var ls          = new List <string>();
            var count       = 0;

            rk.Del("lockObj");

            while (count <= 30)
            {
                ThreadPool.QueueUserWorkItem(s =>
                {
                    if (rl.GetLock())
                    {
                        ls.Add("got!");
                    }

                    count++;
                });
                //Task.Run(new Action(() =>
                //{
                //    if (rl.GetLock())
                //        ls.Add("got!");

                //    count++;
                //}));

                Thread.Sleep(10);
            }
            //for (int i = 0; i < threadCount; i++)
            //{
            //    new Thread(() =>
            //    {
            //        if (rl.GetLock())
            //            ls.Add("got!");
            //    }).Start();

            //    Thread.Sleep(5);
            //}

            Thread.Sleep(10000);

            Assert.True(ls.Count > 0);
        }
        public void LockReentry_DontReleaseEarly()
        {
            UseDatabase(Database =>
            {
                using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(60)))
                {
                    using (var lock3 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(5)))
                    {

                    } //Make sure the lock isn't removed when the nested lock is disposed
                  
                    Assert.Throws<TimeoutException>(() =>
                    {
                        var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMilliseconds(1));
                    });
                }
            });
        }
        public void LockReentry_ExtendLock()
        {
            UseDatabase(Database =>
            {
                using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(10)))
                {
                    using (var lock3 = new RedisLock(Database, "lock", "1", TimeSpan.FromMinutes(1)))
                    {

                    }
                    Thread.Sleep(20);
                    Assert.Throws<TimeoutException>(() =>
                    {
                        var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMilliseconds(1));
                    });
                }
            });
        }
Exemple #33
0
 internal static void DoWork([NotNull] IDatabase redis, [NotNull] RedisKey key, [NotNull] TimeSpan timeOut, [NotNull] TimeSpan sleep, ref int concurrentCount)
 {
     try
     {
         using (var testLock = new RedisLock(redis, key, Thread.CurrentThread.ManagedThreadId.ToString(), timeOut))
         {
             Thread.Sleep(sleep);
             concurrentCount++;
         };
     }
     catch (TimeoutException)
     {
     }
     catch (Exception)
     {
         throw;
     }
 }
 public override LockResult TryGetDistributedLock(TimeSpan?getlockTimeOut, TimeSpan?taskrunTimeOut)
 {
     if (lockresult == LockResult.Success)
     {
         throw new Exception("检测到当前锁已获取");
     }
     _client = DistributedLockConfig.GetRedisPoolClient();
     //当其获取锁后,redis连接资源会一直占用,直到获取锁的资源释放后,连接才会跳出,可能会导致连接池资源的浪费。
     try
     {
         this._lock = new RedisLock(_client as RedisClient, key, getlockTimeOut);
         lockresult = LockResult.Success;
     }
     catch (Exception exp)
     {
         LogManager.DefaultLogger.Error(exp, "redis分布式尝试锁系统级别严重异常");
         lockresult = LockResult.LockSystemExceptionFailure;
     }
     return(lockresult);
 }
 public void LockRelease()
 {
     UseDatabase(Database =>
     {
         using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMinutes(1)))
         {
         }
         using (var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMinutes(1)))
         {
         }
     });
 }
        public void LockCollision()
        {
            UseDatabase(Database =>
            {
                using (var lock1 = new RedisLock(Database, "lock", "1", TimeSpan.FromMilliseconds(30)))
                {
                    Thread.Sleep(20); //Sleep to give the wait loop time to run. If not set high enough lock2 will Timeout
                    using (var lock2 = new RedisLock(Database, "lock", "2", TimeSpan.FromMilliseconds(30)))
                    {

                    }
                }
            });
        }