.net实现redis下单超卖(jmeter高并发测试)(自己记录用)
业务代码
注册时就初始化100个库存
public class UserRedisHelper : RedisHelper<UserMark>
{public static void BindRedis(){if (RedisServer.Cache == null)throw new Exception("initalize first");Initialization(RedisServer.UserCache);UserRedisHelper.Set("seckill:stock:huawei_phone", 100);}
}下单接口
//方法外注册private static readonly ThreadLocal<Random> _threadLocalRandom =new ThreadLocal<Random>(() => new Random());#region
// <summary>
// 测试masstransit发送消息
// </summary>
/// <returns></returns>
[HttpGet("testRedisGet")]
[Log(Title = "TestMessageLost", BusinessType = BusinessType.EXPORT, IsSaveResponseData = false)]
[AllowAnonymous]
public IActionResult TestRedisGet(int userId)
{userId = _threadLocalRandom.Value.Next(1000, 10000);// 1.检查用户是否已下单(无锁)string userRecordKey = $"seckill:user:record:{userId}";if (UserRedisHelper.Exists(userRecordKey)){return BadRequest("您已参与过该商品秒杀,不可重复下单");}// 2. 检查库存(无锁,并发时会超卖)string stockKey = "seckill:stock:huawei_phone";int currentStock = UserRedisHelper.Get<int>(stockKey);if (currentStock <= 0){return BadRequest("手慢了,商品已抢完");}Thread.Sleep(1);// 3. 扣减库存(无锁,多实例并发时会超卖)UserRedisHelper.Set(stockKey, currentStock - 1);// 4. 记录用户下单(无锁,可能重复记录)UserRedisHelper.Set(userRecordKey, 1, 600); // 10分钟过期return Ok("秒杀成功!");
}
#endregion需要两个实例,两个端口分别是 8888 8890 这两个端口分别抢redis的同一个资源。
jmeter




运行后,用户超过100,超卖了

实现分布式锁

