windows下使用redis解决.net6.0下人工调用接口时分配位置的并发问题
使用了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["操作频繁,稍后再试"]); }
业务中调用
本文来自博客园,作者:十四,转载请注明原文链接:https://www.cnblogs.com/yanghucheng/p/18208318