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

共 2372字,需浏览 5分钟

 ·

2022-01-19 12:29

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

Redis预减库存

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

思路:

  1. 系统初始化的时候,将商品库存加载到Redis 缓存中保存
  2. 收到请求的时候,现在Redis中拿到该商品的库存值,进行库存预减,如果减完之后库存不足,直接返回逻辑Exception就不需要访问数据库再去减库存了,如果库存值正确,进行下一步
  3. 将请求入队,立即给前端返回一个值,表示正在排队中,然后进行秒杀逻辑,后端队列进行秒杀逻辑,前端轮询后端发来的请求,如果秒杀成功,返回秒杀,成功,不成功就返回失败。

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

  1. 前端显示

第一步:预减库存

/**
 * 秒杀接口优化之---   第一步:  系统初始化后就将所有商品库存放入 缓存
 */
@Override
public void afterPropertiesSet() throws Exception {
    List 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 isOverMap = new HashMap();

/**
 * 秒杀接口优化之---   第一步:  系统初始化后就将所有商品库存放入 缓存
 */
@Override
public void afterPropertiesSet() throws Exception {
    List 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 实战笔记!
浏览 28
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报