Home  >  Article  >  Database  >  How to realize flash sale scenario of inventory reduction through redis

How to realize flash sale scenario of inventory reduction through redis

WBOY
WBOYforward
2023-06-02 09:04:20747browse

The main purpose of Redis inventory reduction is to reduce access to the database. The previous inventory reduction directly accessed the database and read the inventory. When high concurrent requests come, a large amount of read data may cause the database to collapse.

Usage ideas:

  • When the system is initialized, the product inventory is loaded into the Redis cache and saved.

  • When receiving the request, first get the inventory value of the product in Redis and pre-reduce the inventory. If the inventory is insufficient after the reduction, a logical Exception will be returned directly without access. The database will then reduce the inventory. If the inventory value is correct, proceed to the next step.

  • Enqueue the request and immediately return a value to the front end, indicating that it is being queued, and then perform the flash killing logic. The backend queue performs the flash killing logic, and the front end polls the requests sent by the back end. , if the flash kill is successful, return the flash kill, success, otherwise it will return failure.

The first step: After the system is initialized, put all product inventory into the cache

/**
 * 秒杀接口优化之---   第一步:  系统初始化后就将所有商品库存放入 缓存
 */
@Override
public void afterPropertiesSet() throws Exception {
    List<GoodsVo> goods = goodsService.getGoodsList();
    if (goods == null) {
        return;
    }
    for (GoodsVo goodsVo : goods) {
        redisService.set(GoodsKey.getId(), goodsVo.getStockCount());
        isOverMap.put(goodsVo.getId(), false);//先初始化 每个商品都是false 就是还有
    }
}

The second step: Pre-reduction inventory is reduced from the cache

/**秒杀接口优化之 ----第二步: 预减库存 从缓存中减库存
 * 利用 redis 中的方法,减去库存,返回值为 减去1 之后的值
 * */
long stock = redisService.decr(GoodsKey.getGoodsStock, "" + goodsId);
/*这里判断不能小于等于,因为减去之后等于 说明还有是正常范围*/
if (stock < 0) {
    isOverMap.put(goodsId, true);//没有库存就设置 对应id 商品的map 为true
    return Result.error(CodeMsg.MIAO_SHA_NO_STOCK);
}

The overall logic is as follows:

1. First read out all the data, initialize it into the cache, and store it in Redis in the form of stock goodid.

2. During the flash sale, first perform pre-reduction inventory detection, and use decr to subtract the inventory of the corresponding product from redis. If the inventory is less than 0, it means that the inventory is insufficient at this time, and there is no need to access the database. Just throw an exception directly.
We also used isOverMap above, which is a memory mark.

Memory mark

Due to interface optimization, many cache operations based on Redis will also bring a great burden to the Redis server when the concurrency is high. If the load on the Redis server can be reduced, Access can also achieve the optimization effect.

So, you can add a memory map to mark whether the inventory of the corresponding product is still there. Before accessing Redis, you can get the inventory mark of the corresponding product in the map, and you can judge without accessing Redis. out of stock.

1. Generate a map, and during initialization, use the ids of all products as keys and mark false to store them in the map.

private Map<Long, Boolean> isOverMap = new HashMap<Long, Boolean>();
/**
 * 秒杀接口优化之---   第一步:  系统初始化后就将所有商品库存放入 缓存
 */
@Override
public void afterPropertiesSet() throws Exception {
    List<GoodsVo> goods = goodsService.getGoodsList();
    if (goods == null) {
        return;
    }
    for (GoodsVo goodsVo : goods) {
        redisService.set(GoodsKey.getGoodsStock, "" + goodsVo.getId(), goodsVo.getStockCount());
        isOverMap.put(goodsVo.getId(), false);//先初始化 每个商品都是false 就是还有
    }
}
/**再优化: 优化 库存之后的请求不访问redis 通过判断 对应 map 的值
  * */
boolean isOver = isOverMap.get(goodsId);
if (isOver) {
     return Result.error(CodeMsg.MIAO_SHA_NO_STOCK);
}

if (stock < 0) {
     isOverMap.put(goodsId, true);//没有库存就设置 对应id 商品的map 为true
}

2. Before pre-reducing inventory, get the mark from the map. If the mark is false, it means the inventory

When the inventory is insufficient, reduce the product inventory in advance and mark it as true. Indicates that the product is out of stock. All requests below will be intercepted, and there is no need to access redis for pre-stock reduction.

So the overall idea of ​​using cache is as follows:

Load the inventory data of the product into the memory, and initialize the memory tag at the same time, that is, store the id of each product in the map, which is initialized to false , before each flash sale logic needs to be executed, the value is obtained in the memory mark. If there is still stock, that is, the return value in the map is false, the flash sale logic will be executed, otherwise an exception will be thrown directly.

When deducting inventory at the same time, you need to determine whether the inventory quantity in the cache is still greater than 0. If it is less than or equal to 0, modify the memory mark.

The above is the detailed content of How to realize flash sale scenario of inventory reduction through redis. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete