很抱歉,您提供的信息不完整,我无法直接给出答案。请您提供更具体的问题或信息,这样我才能更好地帮助您。

2026-03-30 15:181阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1362个文字,预计阅读时间需要6分钟。

很抱歉,您提供的信息不完整,我无法直接给出答案。请您提供更具体的问题或信息,这样我才能更好地帮助您。

前言:以下是Redis分布式锁常用概念说明:设置、获取、过期时间、删除。

1、Setnx 命令说明:SETNX key value,将 key 的值设置为 value,当且仅当 key 不存在。

若给定的 key 已经存在,则不进行任何操作。若给定的 key 不存在,则创建一个新键,并将键值设为 value,如果键值设置成功,则返回 1。如果键值设置失败,则返回 0。

前言

下面是Redis分布式锁常用的概念说明:设置、获取、过期时间、删除。

1、 Setnx

很抱歉,您提供的信息不完整,我无法直接给出答案。请您提供更具体的问题或信息,这样我才能更好地帮助您。

  • 命令:SETNX key value
  • 说明:将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 SETNX 不做任何动作。SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。 时间复杂度:O(1)
  • 返回值:设置成功,返回1 ; 设置失败,返回 0

2、Getset

  • 命令:GETSET key value
  • 说明:将给定 key 的值设为 value ,并返回 key 的旧值(old value)。当 key 存在但不是字符串类型时,返回一个错误。 时间复杂度:O(1)
  • 返回值:返回给定 key 的旧值; 当 key 没有旧值时,也即是, key 不存在时,返回 nil 。

3、Expire

  • 命令:EXPIRE key seconds
  • 说明:为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。 时间复杂度:O(1)
  • 返回值:设置成功返回 1 ;当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。

4、Del

  • 命令:DEL key [key ...]
  • 说明:删除给定的一个或多个 key 。不存在的 key 会被忽略。 时间复杂度:O(N); N 为被删除的 key 的数量。删除单个字符串类型的 key ,时间复杂度为O(1)。 删除单个列表、集合、有序集合或哈希表类型的 key ,时间复杂度为O(M), M为以上数据结构内的元素数量。

锁的分类说明:

相对方 相对方 悲观锁 乐观锁 公平锁 非公平锁 独享锁 共享锁 线程锁 进程锁

一、StackExchange.Redis执行Lua脚本实现商品秒杀

以下以.NET 7控制台为实例测试

1.StackExchange.Redis封装

using StackExchange.Redis; namespace Redis { public class RedisHelper { #region Fileds private static string? _redisConnection= "127.0.0.1:6379,defaultDatabase=1"; private static int _db = 0; private static ConnectionMultiplexer? connection; #endregion #region Constructors public RedisHelper() { } 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; } } #endregion #region Methons /// <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 bool KeyExists(string key) { return CacheRedis.KeyExists(key); } /// <summary> /// 删除单个key /// </summary> /// <param name="key">redis key</param> /// <returns>是否删除成功</returns> public bool KeyDelete(string key) { return CacheRedis.KeyDelete(key); } /// <summary> /// redis加锁 /// </summary> /// <param name="key">需要加锁的锁名</param> /// <param name="values">需要加锁的值</param> /// <param name="expireTimeSeconds">该锁自动到期时间,如果没其他要求可设置为最大时常,该方式一定要手动解锁</param> /// <exception cref="Exception"></exception> #region 分布式锁 public static bool LockByRedis(string key, string values) { try { //expireTimeSeconds = expireTimeSeconds > 20 ? 10 : expireTimeSeconds; //var data = TimeSpan.FromSeconds(expireTimeSeconds); //var token = Environment.MachineName; //bool lockflag = CacheRedis.LockTake(key, Thread.CurrentThread.ManagedThreadId, TimeSpan.FromSeconds(expireTimeSeconds)); 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 { // Thread.CurrentThread.ManagedThreadId //Environment.MachineName return CacheRedis.LockRelease(key, valuse); } catch (Exception ex) { throw new Exception($"Redis加锁异常:原因{ex.Message}"); } } #endregion #endregion } }

2.秒杀代码

using Redis; int count=11; Console.WriteLine($"进入秒杀时刻,进入时间{DateTime.Now}"); Parallel.For(0, 1000, i => { //锁键-值 var lockKey = "lockKey"; var lockValue = Guid.NewGuid().ToString("N"); //加锁 bool result = RedisHelper.LockByRedis(lockKey, lockValue); if (!result) { Console.WriteLine("没有抢到锁,这次请求停止"); return; } string data = RedisHelper.GetStringKey("Sum").ToString(); int sum = int.Parse(string.IsNullOrEmpty(data) ? "0" : data); if (sum <= 0) { RedisHelper.StringSet("Sum", count.ToString()); } else { if (sum <=count) { count--; Console.WriteLine("商品还剩:" + sum.ToString()); RedisHelper.StringSet("Sum", count.ToString()); } } //释放锁 var unlock = RedisHelper.UnLockByRedis(lockKey, lockValue); }); Console.WriteLine($"结束秒杀时刻,结束时间{DateTime.Now}");

3.效果

本文共计1362个文字,预计阅读时间需要6分钟。

很抱歉,您提供的信息不完整,我无法直接给出答案。请您提供更具体的问题或信息,这样我才能更好地帮助您。

前言:以下是Redis分布式锁常用概念说明:设置、获取、过期时间、删除。

1、Setnx 命令说明:SETNX key value,将 key 的值设置为 value,当且仅当 key 不存在。

若给定的 key 已经存在,则不进行任何操作。若给定的 key 不存在,则创建一个新键,并将键值设为 value,如果键值设置成功,则返回 1。如果键值设置失败,则返回 0。

前言

下面是Redis分布式锁常用的概念说明:设置、获取、过期时间、删除。

1、 Setnx

很抱歉,您提供的信息不完整,我无法直接给出答案。请您提供更具体的问题或信息,这样我才能更好地帮助您。

  • 命令:SETNX key value
  • 说明:将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 SETNX 不做任何动作。SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。 时间复杂度:O(1)
  • 返回值:设置成功,返回1 ; 设置失败,返回 0

2、Getset

  • 命令:GETSET key value
  • 说明:将给定 key 的值设为 value ,并返回 key 的旧值(old value)。当 key 存在但不是字符串类型时,返回一个错误。 时间复杂度:O(1)
  • 返回值:返回给定 key 的旧值; 当 key 没有旧值时,也即是, key 不存在时,返回 nil 。

3、Expire

  • 命令:EXPIRE key seconds
  • 说明:为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。 时间复杂度:O(1)
  • 返回值:设置成功返回 1 ;当 key 不存在或者不能为 key 设置生存时间时(比如在低于 2.1.3 版本的 Redis 中你尝试更新 key 的生存时间),返回 0 。

4、Del

  • 命令:DEL key [key ...]
  • 说明:删除给定的一个或多个 key 。不存在的 key 会被忽略。 时间复杂度:O(N); N 为被删除的 key 的数量。删除单个字符串类型的 key ,时间复杂度为O(1)。 删除单个列表、集合、有序集合或哈希表类型的 key ,时间复杂度为O(M), M为以上数据结构内的元素数量。

锁的分类说明:

相对方 相对方 悲观锁 乐观锁 公平锁 非公平锁 独享锁 共享锁 线程锁 进程锁

一、StackExchange.Redis执行Lua脚本实现商品秒杀

以下以.NET 7控制台为实例测试

1.StackExchange.Redis封装

using StackExchange.Redis; namespace Redis { public class RedisHelper { #region Fileds private static string? _redisConnection= "127.0.0.1:6379,defaultDatabase=1"; private static int _db = 0; private static ConnectionMultiplexer? connection; #endregion #region Constructors public RedisHelper() { } 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; } } #endregion #region Methons /// <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 bool KeyExists(string key) { return CacheRedis.KeyExists(key); } /// <summary> /// 删除单个key /// </summary> /// <param name="key">redis key</param> /// <returns>是否删除成功</returns> public bool KeyDelete(string key) { return CacheRedis.KeyDelete(key); } /// <summary> /// redis加锁 /// </summary> /// <param name="key">需要加锁的锁名</param> /// <param name="values">需要加锁的值</param> /// <param name="expireTimeSeconds">该锁自动到期时间,如果没其他要求可设置为最大时常,该方式一定要手动解锁</param> /// <exception cref="Exception"></exception> #region 分布式锁 public static bool LockByRedis(string key, string values) { try { //expireTimeSeconds = expireTimeSeconds > 20 ? 10 : expireTimeSeconds; //var data = TimeSpan.FromSeconds(expireTimeSeconds); //var token = Environment.MachineName; //bool lockflag = CacheRedis.LockTake(key, Thread.CurrentThread.ManagedThreadId, TimeSpan.FromSeconds(expireTimeSeconds)); 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 { // Thread.CurrentThread.ManagedThreadId //Environment.MachineName return CacheRedis.LockRelease(key, valuse); } catch (Exception ex) { throw new Exception($"Redis加锁异常:原因{ex.Message}"); } } #endregion #endregion } }

2.秒杀代码

using Redis; int count=11; Console.WriteLine($"进入秒杀时刻,进入时间{DateTime.Now}"); Parallel.For(0, 1000, i => { //锁键-值 var lockKey = "lockKey"; var lockValue = Guid.NewGuid().ToString("N"); //加锁 bool result = RedisHelper.LockByRedis(lockKey, lockValue); if (!result) { Console.WriteLine("没有抢到锁,这次请求停止"); return; } string data = RedisHelper.GetStringKey("Sum").ToString(); int sum = int.Parse(string.IsNullOrEmpty(data) ? "0" : data); if (sum <= 0) { RedisHelper.StringSet("Sum", count.ToString()); } else { if (sum <=count) { count--; Console.WriteLine("商品还剩:" + sum.ToString()); RedisHelper.StringSet("Sum", count.ToString()); } } //释放锁 var unlock = RedisHelper.UnLockByRedis(lockKey, lockValue); }); Console.WriteLine($"结束秒杀时刻,结束时间{DateTime.Now}");

3.效果