使用了nuget包包括了:CSRedisCore,StackExchange.Redis,MyStack.DistributedLocking,Microsoft.Extensions.Configuration
安装Redis并注册为windows服务 直接参考这位兄弟的成果:
https://www.cnblogs.com/qingheshiguang/p/17952623
注册服务:
配置文件appsetting.json中加上Redis的连接字符串
"Redis": "127.0.0.1:6379",
Program.cs中添加注册服务
// 添加并发锁支持
builder.Services.AddDistributedLock(builder.Configuration["Redis"]);
using CSRedis;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Redis;
using Utility.Concurrent;
namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
{
/// <summary>
/// 添加并发锁支持
/// </summary>
/// <param name="services"></param>
/// <param name="connectionString"></param>
/// <returns></returns>
public static IServiceCollection AddDistributedLock(this IServiceCollection services, string connectionString)
{
RedisHelper.Initialization(new CSRedisClient(connectionString));
services.AddSingleton<IDistributedCache>(new CSRedisCache(RedisHelper.Instance));
services.AddSingleton(typeof(IDistributedLock), typeof(DistributedLock));
return services;
}
}
}
redis客户端实现
using CSRedis;
namespace Concurrent
{
public class DistributedLock : IDistributedLock
{
private const string _lockKey = "LockKey";
public async Task<bool> TryLockAsync(string key, int lockExpirySeconds = 10, long waitLockSeconds = 60)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException("锁键值不能为空。");
}
DateTime begin = DateTime.Now;
while (true)
{
if (await RedisHelper.SetAsync($"{_lockKey}.{key}", Thread.CurrentThread.ManagedThreadId, lockExpirySeconds, RedisExistence.Nx))
{
return true;
}
//不等待锁则返回
if (waitLockSeconds == 0)
{
break;
}
//超过等待时间,则不再等待
if ((DateTime.Now - begin).TotalSeconds >= waitLockSeconds)
{
break;
}
Thread.Sleep(100);
}
return false;
}
public async Task UnLockAsync(string key)
{
await RedisHelper.DelAsync($"{_lockKey}.{key}");
}
public async Task<T> LockExecuteAsync<T>(string key, Func<Task<T>> handle, int lockExpirySeconds = 10, long waitLockSeconds = 60)
{
if (await TryLockAsync(key, lockExpirySeconds, waitLockSeconds))
{
try
{
return await handle?.Invoke();
}
finally
{
try { await UnLockAsync(key); } finally { }
}
}
return await Task.FromResult(default(T));
}
}
}
//锁定分配的目标库位
var hasLock = await _distributedLock.TryLockAsync(LocationCode, 5, 10);
if (!hasLock)
{
throw new BizException(_Localizer["操作频繁,稍后再试"]);
}
业务中调用