C#基于StackExchange.Redis实现分布式锁

demo例子:实现库存减少

程序一:

 如果程序一在枷锁时打断点暂停,另开程序二获取该锁情况:

 程序一继续执行,处理完后的情况:

 程序一:

namespace RedisClient
{
    internal class Program
    {
        private static string _stockKey = "stock";
        static void Main(string[] args)
        {
            Alternative();
            Console.ReadKey();
        }
        public static void Alternative()
        {
            if (!RedisHelper.KeyExists(_stockKey))
                RedisHelper.StringSet(_stockKey, "100");//库存
            var lockKey = "lockKey";
            var lockValue = Guid.NewGuid().ToString("N");
            bool result = RedisHelper.LockByRedis(lockKey, lockValue);
            if (!result)
            {
                Console.WriteLine("没有抢到锁,这次请求停止");
                return;
            }
            Console.WriteLine("抢到锁,开始处理业务");
            string data = RedisHelper.GetStringKey(_stockKey).ToString();
            int sum = int.Parse(string.IsNullOrEmpty(data) ? "0" : data);
            if (sum <= 0)
            {
                Console.WriteLine("库存不足!");
            }
            else
            {
                Console.WriteLine("减少库存:1");
                sum -= 1;
                Console.WriteLine($"剩余库存:{sum}");
                RedisHelper.StringSet(_stockKey, sum.ToString());
            }
            var unlock = RedisHelper.UnLockByRedis(lockKey, lockValue);
            if (unlock)
                Console.WriteLine("释放锁成功!");
        }
    }
}

程序二:

namespace RedisClient2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var count = 0;
            while (count < 100)
            {
                var lockKey = "lockKey";
                var lockValue = Guid.NewGuid().ToString("N");
                bool result = RedisHelper.LockByRedis(lockKey, lockValue);
                if (!result)
                {
                    Console.WriteLine("没有抢到锁,这次请求停止");
                }
                if (result)
                {
                    Console.WriteLine("抢到锁,开始处理业务逻辑");
                    Console.WriteLine($"{RedisHelper.GetStringKey("stock")}");
                    RedisHelper.UnLockByRedis(lockKey, lockValue);
                    Console.WriteLine("释放锁");
                    return;
                }
                count++;
                Thread.Sleep(2000);
            }
            Console.ReadKey();
        }
    }
}

公共类:

namespace RedisClient
{
    public class RedisHelper
    {

        private static string _redisConnection= "192.168.1.***:6379,password=****,defaultDatabase=6,abortConnect=false";
        private static int _db = 6;
        private static ConnectionMultiplexer connection;

        public static ConnectionMultiplexer CacheConnection
        {
            get
            {
                try
                {
                    if (connection == null || !connection.IsConnected)
                    {
                        connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(_redisConnection)).Value;
                    }
                }
                catch (Exception ex)
                {
                    return null;
                }
                return connection;
            }
        }

        /// <summary>
        /// 获取当前数据库
        /// </summary>
        public static IDatabase CacheRedis => CacheConnection.GetDatabase(_db);

        /// <summary>
        /// 新增单条值
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public static bool StringSet(string key, string values)
        {
            if (string.IsNullOrEmpty(key) && string.IsNullOrEmpty(values))
                throw new AggregateException("values or is null");
            return CacheRedis.StringSet(key, values);
        }

        /// <summary>
        /// 查询单个key值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static RedisValue GetStringKey(string key)
        {
            return CacheRedis.StringGet(key);
        }

        /// <summary>
        /// 判断key是否存储
        /// </summary>
        /// <param name="key">redis key</param>
        /// <returns></returns>
        public static bool KeyExists(string key)
        {
            return CacheRedis.KeyExists(key);
        }

        /// <summary>
        /// 删除单个key
        /// </summary>
        /// <param name="key">redis key</param>
        /// <returns>是否删除成功</returns>
        public static bool KeyDelete(string key)
        {
            return CacheRedis.KeyDelete(key);
        }

        /// <summary>
        /// redis 枷锁
        /// </summary>
        /// <param name="key">需要加锁的锁名</param>
        /// <param name="expireTimeSeconds">该锁自动到期时间  如果没其他要求可设置为最大时常   该方式一定要手动解锁</param>
        /// <exception cref="Exception"></exception>
        public static bool LockByRedis(string key, string values)
        {
            try
            {
                bool lockflag = CacheRedis.LockTake(key, values, TimeSpan.MaxValue);
                if (!lockflag)
                {
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                throw new Exception($"Redis加锁异常:原因{ex.Message}");
            }
        }

        /// <summary>
        /// 解锁
        /// </summary>
        /// <param name="key">需要解锁的锁名</param>
        /// <param name="values">需要解锁的值</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static bool UnLockByRedis(string key, string valuse)
        {
            try
            {
                return CacheRedis.LockRelease(key, valuse);
            }
            catch (Exception ex)
            {
                throw new Exception($"Redis加锁异常:原因{ex.Message}");
            }
        }
    }
}

 

参考:https://www.cnblogs.com/OneSeting/p/15576542.html

 

posted @ 2025-05-20 17:14  点终将连成线  阅读(118)  评论(0)    收藏  举报