2881099 / csredis

.NET Core or .NET Framework 4.0+ client for Redis and Redis Sentinel (2.8) and Cluster. Includes both synchronous and asynchronous clients.
MIT License
2.01k stars 414 forks source link

关于 RedisClientLock 分布式锁在持有锁的期间,其他请求还会再次持有锁的bug #419

Closed MarsonShine closed 2 years ago

MarsonShine commented 2 years ago

环境: windows10 CSRedisCore 3.6.8 .net5

复现代码

public IActionResult Sync()
{
      string guid = Guid.NewGuid().ToString();
      using (RedisHelper.Lock("LockName", TimeSpan.FromSeconds(15).Seconds))
      {
            _logger.LogWarning("{guid} 占有锁...", guid);
            Thread.Sleep(TimeSpan.FromSeconds(5));
      }
      _logger.LogWarning("{guid} 释放锁...", guid);
      return Ok();
}

在5秒内多次请求,就会发现有偶发性的出现在没有释放锁时候,重复持有锁。 以下是测试的截图

图片
adxpcc commented 2 years ago
      using (var o = RedisHelper.Lock("LockName", TimeSpan.FromSeconds(15).Seconds))
      {
if(o ==null)
{
超时//
}else{
            _logger.LogWarning("{guid} 占有锁...", guid);
            Thread.Sleep(TimeSpan.FromSeconds(5));
      }
}
      _logger.LogWarning("{guid} 释放锁...", guid);
      return Ok();
MarsonShine commented 2 years ago
      using (var o = RedisHelper.Lock("LockName", TimeSpan.FromSeconds(15).Seconds))
      {
if(o ==null)
{
超时//
}else{
            _logger.LogWarning("{guid} 占有锁...", guid);
            Thread.Sleep(TimeSpan.FromSeconds(5));
      }
}
      _logger.LogWarning("{guid} 释放锁...", guid);
      return Ok();

就是说我demo的那段代码中,写法有误? RedisHelper.Lock是同步方法,如果锁已被占用,就会一直等待,超时不会报错而是返回null。 我去renew一下,感谢回复。

adxpcc commented 2 years ago
      using (var o = RedisHelper.Lock("LockName", TimeSpan.FromSeconds(15).Seconds))
      {
if(o ==null)
{
超时//
}else{
            _logger.LogWarning("{guid} 占有锁...", guid);
            Thread.Sleep(TimeSpan.FromSeconds(5));
      }
}
      _logger.LogWarning("{guid} 释放锁...", guid);
      return Ok();

就是说我demo的那段代码中,写法有误? RedisHelper.Lock是同步方法,如果锁已被占用,就会一直等待,超时不会报错而是返回null。 我去renew一下,感谢回复。

另外 你这里还缺少释放锁的步骤~

MarsonShine commented 2 years ago
      using (var o = RedisHelper.Lock("LockName", TimeSpan.FromSeconds(15).Seconds))
      {
if(o ==null)
{
超时//
}else{
            _logger.LogWarning("{guid} 占有锁...", guid);
            Thread.Sleep(TimeSpan.FromSeconds(5));
      }
}
      _logger.LogWarning("{guid} 释放锁...", guid);
      return Ok();

就是说我demo的那段代码中,写法有误? RedisHelper.Lock是同步方法,如果锁已被占用,就会一直等待,超时不会报错而是返回null。 我去renew一下,感谢回复。

另外 你这里还缺少释放锁的步骤~

刚测试了,是写法有误。因为超时返回了null(不过反倒有些麻烦了,需要手动再次等待... 囧)。 不用手动释放啊,lockclient返回的是dispose类型,using自动释放的。

MarsonShine commented 2 years ago

是写法问题,close