不超卖实现

本文介绍了Redis的decr命令在高并发环境下的原子性、性能优势,以及如何通过setnx加锁防止超卖。此外,还讨论了使用Redisson进行库存管理、延迟消费队列和定时任务的应用实例。
摘要由CSDN通过智能技术生成

decr(互斥,一般不会产生超卖)

decr 命令在 Redis 中的主要好处包括: 原子性操作:decr 是一个原子操作,这意味着即使在高并发环境下,对于同一 key 的递减操作也是互斥的,不会出现竞态条件(race condition),保证了数据的一致性和完整性。 高性能计算:在 Redis 这种内存数据库中,执行 decr 操作非常迅速,相比起每次都需要从数据库读取数据、修改后再写回的传统数据库操作,Redis 可以显著提升计数器类业务场景的性能。 简化开发:在诸如统计访问量、商品库存扣减、积分系统中扣除积分等应用场景下,直接调用 decr 命令可以大大简化开发工作,无需编写额外的加减逻辑和事务处理代码。 空间效率:由于 Redis 内部实现了对整数值的优化存储,使用 decr 更新整数值时,仅需修改内存中的数值,不需要像文本或者其他复杂类型那样重新分配存储空间。

setnx 加锁兜底

setnx 加锁是一种兜底手段,避免后续有库存的恢复,(rediss挂了,人为恢复)导致库存从96消耗后又回到了98重复消费。所以对于每个key加锁,98、97、96... 即使有恢复库存也不会导致超卖。【setnx 在 redisson 是用 trySet 实现】

 redissonClient.getBucket(key).trySet("lock")

在 Redisson 中,Bucket 类用于操作单个值的 Redis 键,其 trySet(V value) 方法尝试将桶(bucket)的值设置为给定值,如果 bucket 之前没有值,则设置成功并返回 true;如果已经有值,则设置失败并返回 false。

延迟消费队列

//    生成消费队列
@Override
public void awardStockConsumeSendQueue(StrategyAwardStockKeyVO strategyAwardStockKeyVO) {
    String cashKey = Constants.RedisKey.STRATEGY_AWARD_COUNT_QUERY_KEY;
    RBlockingQueue<Object> blockingQueue = redisService.getBlockingQueue(cashKey);
    RDelayedQueue<Object> delayedQueue = redisService.getDelayedQueue(blockingQueue);
    delayedQueue.offer(strategyAwardStockKeyVO,3, TimeUnit.SECONDS);
}

消费队列是在RuleStockLogicTreeNode(规则树)调用生成, !!!相当于权重装配没有走库存,不进行库存扣减

定时任务

Cron 表达式 "0/5 * * * * ?" 解释如下: 第一位 0:表示分钟域的值,这里意味着从第 0 分钟开始,每隔 5 分钟执行一次(即 0, 5, 10, 15, ...)。 接下来的四个星号 * 分别代表小时域、月份中的日期域、月份域、星期域,均表示任意值,即不作任何限制。 最后一个问号 ? 在某些 Cron 表达式实现中表示月份中的日期(day-of-month)和星期(day-of-week)两个字段不必同时满足,只要其中之一满足条件即可执行任务。但在 Spring 的 @Scheduled 注解中,它通常用来兼容 Quartz Cron 表达式,并无特殊含义。 因此,整个表达式意味着该方法将会每 5 分钟执行一次,不受日期、小时或其他日历因素影响。

1.拿消费队列

2.更新数据库库存

部分代码解释

 @Override
    public Long getAtomicLong(String key) {
return  redissonClient.getAtomicLong(key).get();
    }
    
该函数通过Redisson客户端获取具有指定键的原子长整型对象,并返回该对象的当前值。    
    
​
    @Override
    public void setAtomicLong(String cacheKey, Integer awardCount) {
        redissonClient.getAtomicLong(cacheKey).set(awardCount);
    }
    
    该函数使用Redisson客户端获取具有给定缓存键的AtomicLong对象,并将指定的奖品数量设置为该AtomicLong对象的值。

! decr setNx都是在这一步

public Boolean subtractionAwardStock(String cacheKey) {
//扣减库存(存的是总库存,为了加锁)
    long surplus = redisService.decr(cacheKey);
    if (surplus < 0) {
        redisService.setValue(cacheKey,0);
        return false;
    };
    String lockKey = cacheKey + Constants.UNDERLINE + surplus;
 Boolean lock=   redisService.setNx(lockKey);
 if (!lock) {
           log.info("策略奖品库存加锁失败,", lockKey);
      }
​
    return lock;
}

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值