当前位置: 首页 > 工具软件 > RedLock.net > 使用案例 >

RedLock使用实例

冀胤运
2023-12-01

获取锁:

SET resource_name my_random_value NX PX 30000

释放锁:

if redis.call("get",KEYS[1]) == ARGV[1] then
  return redis.call("del",KEYS[1])
else
  return 0
end

RedLock.net 集成:

  1. 创建 .NETCore API 项目
  2. NuGet 安装 RedLock.net
Install-Package RedLock.net
  1. appsettings.json 添加 redis 配置
{
  "RedisUrl": "127.0.0.1:6379", // 多个用,分割
  ...
}
  1. 添加 ProductService.cs,模拟商品购买
// 有10个商品库存,如果同时启动多个API服务进行测试,这里改成存数据库或其他方式
private static int stockCount = 10;
public async Task<bool> BuyAsync()
{
  // 模拟执行的逻辑代码花费的时间
  await Task.Delay(new Random().Next(100, 500));
  if (stockCount > 0)
  {
    stockCount--;
    return true;
  }
  return false;
}
  1. 修改 Startup.cs ,创建 RedLockFactory
    定义 RedLockFactory 变量:
private RedLockFactory lockFactory;

添加方法:

private RedLockFactory GetRedLockFactory()
{
  var redisUrl = Configuration["RedisUrl"];
  if (string.IsNullOrEmpty(redisUrl))
  {
    throw new ArgumentException("RedisUrl 不能为空");
  }
  var urls = redisUrl.Split(",").ToList();
  var endPoints = new List<RedLockEndPoint>();
  foreach (var item in urls)
  {
    var arr = item.Split(":");
    endPoints.Add(new DnsEndPoint(arr[0], Convert.ToInt32(arr[1])));
  }
  return RedLockFactory.Create(endPoints);
}

在 ConfigureServices 注入 IDistributedLockFactory:

lockFactory = GetRedLockFactory();
services.AddSingleton(typeof(IDistributedLockFactory), lockFactory);
services.AddScoped(typeof(ProductService));

修改 Configure,应用程序结束时释放 lockFactory :

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
{
  ...

  lifetime.ApplicationStopping.Register(() =>
  {
    lockFactory.Dispose();
  });
}
  1. 在 Controller 添加方法 DistributedLockTest
private readonly IDistributedLockFactory _distributedLockFactory;
private readonly ProductService _productService;

public HomeController(IDistributedLockFactory distributedLockFactory,
  ProductService productService)
{
  _distributedLockFactory = distributedLockFactory;
  _productService = productService;
}

[HttpGet]
public async Task<bool> DistributedLockTest()
{
  var productId = "id";
  // resource 锁定的对象
  // expiryTime 锁定过期时间,锁区域内的逻辑执行如果超过过期时间,锁将被释放
  // waitTime 等待时间,相同的 resource 如果当前的锁被其他线程占用,最多等待时间
  // retryTime 等待时间内,多久尝试获取一次
  using (var redLock = await _distributedLockFactory.CreateLockAsync(productId, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(1), TimeSpan.FromMilliseconds(20)))
  {
    if (redLock.IsAcquired)
    {
      var result = await _productService.BuyAsync();
      return result;
    }
    else
    {
      Console.WriteLine($"获取锁失败:{DateTime.Now}");
    }
  }
  return false;
}
  1. 调用接口测试
Parallel.For(1, 16, (i) =>
{
  var stopwatch = new Stopwatch();
  stopwatch.Start();
  var data = GetAsync($"http://localhost:5000/home/distributedLockTest").Result;
  stopwatch.Stop();
  Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId}, Result:{data}, Time:{stopwatch.ElapsedMilliseconds}");
});
 类似资料: