1、前言
Redis + 原子性 + MQ隊列
- 引入Redis緩存+消息隊列代替基于記憶體緩存和隊列,資料可持化解決了丢失問題.
- Redis是單線程的,利用api自身的原子性,進而可以幹掉lock鎖.
- 引入程序外的緩存,進而可以把生産者和消費者解耦分離,可以作為兩個獨立的服務運作.
2、示例
關于扣減庫存量
/// <summary>
/// 扣減庫存接口 秒殺/搶購 Redis+隊列
/// </summary>
/// <returns></returns>
[HttpPost("Order")]
public IActionResult Order()
{
//扣減庫存量
var count = _redis.StringDecrement("products:1");
if (count > 0)
{
//下單存到隊列中
_redis.ListLeftPush("OrderPop", #34;{Guid.NewGuid()},{1}");
}
else
{
return Json(new { Code = 201, Msg = "搶購失敗" });
}
return Json(new { Code = 200, Msg = "搶購成功" });
}
/// <summary>
/// 訂單處理
/// </summary>
/// <returns></returns>
public async Task<bool> OrderHandle()
{
//redis隊列的消費者
var data = (string)_redis.ListRightPop("OrderPop");
if (!string.IsNullOrEmpty(data))
{
var _data = data.Split(",");
var id = int.Parse(_data[1]);
var kill = await repository.FirstOrDefault(q => q.ID == id);
if (kill != null)
{
kill.use_qty += 1;
kill.quantity -= 1;
kill.ModifyTime = DateTime.Now;
var result = await repository.Update(kill, true, q => new { q.use_qty, q.quantity, q.ModifyTime });
//建立訂單
//
return result > 0;
}
}
return false;
}
//定時作業處理訂單
public class OrderHandleJob : Job
{
private readonly ILogger<OrderHandleJob> logging;
private readonly It_activities_seckillService service;
public OrderHandleJob(ILogger<OrderHandleJob> _logging, It_activities_seckillService _service)
{
logging = _logging;
service = _service;
}
/// <summary>
/// 定時任務處理
/// </summary>
[Invoke(Interval = 1000, SkipWhileExecuting = true)]
public void Run()
{
var result = service.OrderHandle().GetAwaiter().GetResult();
if (result)
logging.LogInformation("成功");
else
logging.LogInformation("失敗");
}
}
-
壓力測試
利用 Jmeter 測試工具
線程數:1000 (表示使用者1000同時執行調用接口)