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

浙公网安备 33010602011771号