2022年11月 .NET CORE工具案例-StackExchange.Redis代码变量方式实现商品秒杀
Posted 微软MVP Eleven
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022年11月 .NET CORE工具案例-StackExchange.Redis代码变量方式实现商品秒杀相关的知识,希望对你有一定的参考价值。
文章目录
前言
下面是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.效果
以上是关于2022年11月 .NET CORE工具案例-StackExchange.Redis代码变量方式实现商品秒杀的主要内容,如果未能解决你的问题,请参考以下文章
2022年11月 .NET CORE工具案例-.NET 7中的Quic通信
2022年11月 .NET CORE工具案例-StackExchange.Redis代码变量方式实现商品秒杀
2022年11月 .NET CORE工具案例-StackExchange.Redis代码变量方式实现商品秒杀
愚公系列2022年12月 .NET CORE工具案例-.NET Core使用PaddleOCRSharp进行身份证和车牌识别