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"]);
Program

 

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;
        }
    }
}
View Code

 

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));
        }
    }
}
DistributedLock
    //锁定分配的目标库位
   var hasLock = await _distributedLock.TryLockAsync(LocationCode, 5, 10);
    if (!hasLock) 
    {
        throw new BizException(_Localizer["操作频繁,稍后再试"]);
    }

业务中调用

posted @ 2024-05-23 13:56  十四  阅读(8)  评论(0编辑  收藏  举报