天天看點

Redis高并發扣減庫存參考方案

作者:簡單d貓

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("失敗");

    }
}
           
  1. 壓力測試

    利用 Jmeter 測試工具

    線程數:1000 (表示使用者1000同時執行調用接口)

Redis高并發扣減庫存參考方案
Redis高并發扣減庫存參考方案
Redis高并發扣減庫存參考方案
Redis高并發扣減庫存參考方案

繼續閱讀