秒杀场景:如何通过 Redis 减库存?

Posted Java技术栈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了秒杀场景:如何通过 Redis 减库存?相关的知识,希望对你有一定的参考价值。

点击关注公众号,Java干货及时送达

Redis预减库存

主要思路减少对数据库的访问,之前的减库存,直接访问数据库,读取库存,当高并发请求到来的时候,大量的读取数据有可能会导致数据库的崩溃。

思路:

  1. 系统初始化的时候,将商品库存加载到Redis 缓存中保存

  2. 收到请求的时候,现在Redis中拿到该商品的库存值,进行库存预减,如果减完之后库存不足,直接返回逻辑Exception就不需要访问数据库再去减库存了,如果库存值正确,进行下一步

  3. 将请求入队,立即给前端返回一个值,表示正在排队中,然后进行秒杀逻辑,后端队列进行秒杀逻辑,前端轮询后端发来的请求,如果秒杀成功,返回秒杀,成功,不成功就返回失败。

(后端请求 单线程 出队,生成订单,减少库存,走逻辑)前端同时轮询

  1. 前端显示

第一步:预减库存

/**
 * 秒杀接口优化之---   第一步:  系统初始化后就将所有商品库存放入 缓存
 */
@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 中的方法,减去库存,返回值为 减去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);

预减库存:

1.先将所有数据读出来,初始化到缓存中,并以 stock + goodid 的形成存入Redis,最新面试题整理好了,大家可以在Java面试库小程序在线刷题。

2.在秒杀的时候,先进行预减库存检测,从redis中,利用decr 减去对应商品的库存,如果库存小于0,说明此时 库存不足,则不需要访问数据库。直接抛出异常即可

内存标记:

由于接口优化很多基于Redis的缓存操作,当并发很高的时候,也会给Redis服务器带来很大的负担,如果可以减少对Redis服务器的访问,也可以达到的优化的效果。

于是,可以加一个内存map,标记对应商品的库存量是否还有,在访问Redis之前,在map中拿到对应商品的库存量标记,就可以不需要访问Redis 就可以判断没有库存了。

1.生成一个map,并在初始化的时候,将所有商品的id为键,标记false 存入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.在预减库存之前,从map中取标记,若标记为false,说明库存

3.预减库存,当遇到库存不足的时候,将该商品的标记置为true,表示该商品的库存不足。这样,下面的所有请求,将被拦截,无需访问redis进行预减库存。

原文链接:https://blog.csdn.net/weixin_38035852/article/details/81174986

版权声明:本文为CSDN博主「Dandy1awcoder」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。


微信官宣:一大波新年红包封面来了!

2021 年发生的 10 件技术大事!!

23 种设计模式实战(很全)

Log4j2 漏洞之 JNDI 到底是个什么鬼?

炸了!Log4j2 再爆漏洞。。

劲爆!Java 协程要来了

重磅官宣:Redis 对象映射框架来了!!

推荐一款代码神器,代码量至少省一半!

程序员精通各种技术体系,45岁求职难!

重磅!Spring Boot 2.6 正式发布

Spring Boot 学习笔记,这个太全了!

关注Java技术栈看更多干货

获取 Spring Boot 实战笔记!

以上是关于秒杀场景:如何通过 Redis 减库存?的主要内容,如果未能解决你的问题,请参考以下文章

秒杀场景:如何通过 Redis 减库存?

电商并发减库存设计,如何做到不超卖

秒杀——接口优化

秒杀系统“减库存”设计的核心逻辑

redis秒杀系统数据同步(保证不多卖)

redis秒杀系统数据同步(保证不多卖)