当前位置: 首页 > news >正文

.net实现秒杀商品(Redis高并发)

1.思想

模拟不同用户在同一时刻对一件商品进行秒杀,每次调用随机一个userId,代表不同的用户。

设置三个键

userRecordKey(记录用户是否已经秒杀过这个商品),

stockKey(商品的库存),

lockKey(互斥锁,是分布式锁机制的核心标识。过这个键的 “存在 / 不存在” 来标识 “是否有线程在操作华为手机的秒杀资源”,从而实现 多线程或者多服务器之间的互斥访问。当某个线程获取锁时,会在 Redis 中创建这个 lockKey。其他线程尝试获取锁时,会检查这个lockKey是否存在,存在则表示 “资源被占用”,需等待或放弃;线程释放锁时,会删除这个 lockKey,释放资源占用。)

如果有一个进程在进行操作,其他线程就会显示秒杀拥挤,等待当前进程释放锁。具体业务逻辑,判断是否有锁后,如果没有则判断是否重复下单 -》检查库存 -》 扣减库存 -》 记录用户 -》释放锁。

2.业务代码

 #region stackRedis封装///<summary>/// stackredis/// </summary>[HttpGet("stackRedis")][AllowAnonymous]public IActionResult StackRedis(){int userId = _threadLocalRandom.Value.Next(1000, 10_000);var userRecordKey = $"usersession:seckill:user:record:{userId}";const string stockKey = "usersession:seckill:stock:huawei_phone";const string lockKey = "usersession:seckill:lock:huawei_phone";var lockVal = Guid.NewGuid().ToString();// 1.原子拿锁bool getKey = StackExchangeRedisHelper.Db.StringSet(lockKey, lockVal,TimeSpan.FromSeconds(10),When.NotExists);Thread.Sleep(10000);if (!getKey)return ToResponse(ResultCode.CUSTOM_ERROR, "秒杀拥挤!");try{// 2.判断重复下单bool reBuy = StackExchangeRedisHelper.Db.KeyExists(userRecordKey);if (reBuy)return ToResponse(ResultCode.CUSTOM_ERROR,"重复下单!");// 3.检查库存int stock = (int)StackExchangeRedisHelper.Db.StringGet(stockKey);if (stock <= 0)return ToResponse(ResultCode.CUSTOM_ERROR, "商品已抢完");// 4.减库存int a = (int)StackExchangeRedisHelper.Db.StringDecrement(stockKey);Console.WriteLine($"当前有{a}");// 5.记录用户StackExchangeRedisHelper.Db.StringSet(userRecordKey,1,TimeSpan.FromMinutes(10));return SUCCESS("秒杀成功!");}finally{//释放锁try{var lua = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";StackExchangeRedisHelper.Db.ScriptEvaluate(lua, new RedisKey[] { lockKey }, new RedisValue[] { lockVal });}catch (Exception ex){Console.WriteLine(ex+"释放 Redis 锁失败,lockKey: {lockKey}"+lockKey);}}}#endregion

3. StackExchangeRedisHelper.cs

基于 StackExchange.Redis 的单例 Redis 连接助手,考虑了连接的自动重建和旧连接的延迟释放,,也可以在controller里自己连接,我觉得这样方便,美观点。

using Infrastructure;
using StackExchange.Redis;
using System;
using System.Threading.Tasks;
namespace ZR.Infrastructure.Helper
{/// <summary>/// Redis,连接单例/// </summary>public static class StackExchangeRedisHelper{private static readonly object _lock = new object();private static ConnectionMultiplexer _mux;///<summary>/// 连接字符串,可在 Program.cs 或 appsettings.json 里先赋值/// </summary>private static string config = AppSettings.GetConfig("StackRedis:Redis") + ",connectTimeout=5000,syncTimeout=3000";// <summary>/// 单例 ConnectionMultiplexer/// </summary>public static ConnectionMultiplexer Mux{get{if (_mux == null || !_mux.IsConnected){lock (_lock){if (_mux == null || !_mux.IsConnected){// 关键修改:不直接 Dispose 旧连接,而是创建新连接后让旧连接被 GC 回收// (避免正在使用旧连接的请求报错)var oldMux = _mux;_mux = ConnectionMultiplexer.Connect(config); // 创建新连接// 延迟释放旧连接(给正在使用的请求留时间完成)if (oldMux != null){Task.Run(() =>{try{// 等待 5 秒后释放旧连接(根据业务调整)Task.Delay(5000).Wait();oldMux.Dispose();}catch { /* 忽略释放失败的异常 */ }});}}}}return _mux;}}/// <summary>/// 默认数据库(0 号)/// </summary>public static IDatabase Db => Mux.GetDatabase();/// <summary>/// 按需获取指定数据库/// </summary>public static IDatabase GetDatabase(int db = 0) => Mux.GetDatabase(db);}
}

4.Appsettings.json

"StackRedis": {"Redis": "localhost:6379"
}

5.jemeter测试(200个线程)

6.结果

http://www.dtcms.com/a/573435.html

相关文章:

  • 解决phpstudy 8.x软件中php8.2.9没有redis扩展的问题
  • 【MCP系列】飞书MCP使用
  • 阜新网站设计淮北市矿务局工程建设公司网站
  • 攻克维吾尔语识别的技术实践(多语言智能识别系统)
  • [Windows] 漫画翻译工具Saber Translator2.5.1
  • 手术机器人智能控制系统基本课时项目化课件(2025.08.25)
  • NATS安装与配置完全指南
  • 开发网站如何选需要注意什么汉川网页设计
  • seo根据什么具体优化想做个卷帘门百度优化网站
  • Rust 练习册 7:高阶生命周期与高阶 trait 限定
  • Linux服务器通过密钥登录服务器
  • 网站开发2008家纺外发加工订单网
  • 广州地铁站路线图广告设计师证怎么考
  • 【拾遗补漏】.NET 常见术语集
  • 从零开发一个简单的Web爬虫(使用Requests和BeautifulSoup)
  • 荷城网站设计做网站找哪家最好
  • Hadoop 分布式计算MapReduce和资源管理Yarn
  • DOM XMLHttpRequest
  • day08(11.5)——leetcode面试经典150
  • XML CDATA 区块详解
  • 网站专题页优化网站推广南京公司
  • 记录GDI+保存位图
  • 市值分析:半导体龙头的估值边界在哪里?——以NVIDIA为案例的概率化拆解
  • 内蒙古创意网站开发微网站建设服务商
  • 网站做全景图极速网站建设定制
  • wordpress新增站点盐城整站优化
  • 网络安全常见的框架漏洞
  • 停车场管理系统基础知识与原理
  • 安卓进阶——跨进程通信
  • 连接模拟器网页进行h5的调试(使用Chrome远程调试(推荐)) 保姆级图文