当前位置: 首页 > news >正文

使用redis读写锁实现抢券功能

思路:100个线程抢3张券。多线程同时操作共享资源,也就是库存,不能超卖。

查询库存(缓存中有从缓存取,缓存没有就查询DB,再缓存起来)(在读锁中实现)

库存>0,更新DB,并删除缓存(放在写锁中实现)。

package com.niuniu.order.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.niuniu.common.vo.Response;
import com.niuniu.order.model.Order;public interface CouponService extends IService<Order> {/*** 100个人抢三张券,每人限购一张* @return*/Response dealCoupon(Long productId, Integer num);
}
package com.niuniu.order.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.niuniu.common.vo.Response;
import com.niuniu.order.feignclient.ProductStoreClient;
import com.niuniu.order.mapper.OrderMapper;
import com.niuniu.order.model.Order;
import com.niuniu.order.service.CouponService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.Objects;@Service
@Slf4j
public class CouponServiceImpl extends ServiceImpl<OrderMapper, Order> implements CouponService {@Autowiredprivate ProductStoreClient productStoreClient;@Resourceprivate RedisTemplate<String, String> redisTemplate;@Resourceprivate RedissonClient redissonClient;/*** 抢券逻辑* @return*/@Overridepublic Response dealCoupon(Long productId, Integer num) {// 1、查询库存Integer stock = this.getStockById(productId);System.out.println(Thread.currentThread().getName()+"读到的剩余量是"+stock);if (stock > 0){// 减少库存this.updateStock(productId, num);}return Response.ok();}/*** 根据商品id查询库存* @param productId* @return*/private Integer getStockById(Long productId){RReadWriteLock rReadWriteLock = redissonClient.getReadWriteLock("READ_WRITE_STOCK_" + productId);RLock rLock = rReadWriteLock.readLock();Integer stock = 0;try{rLock.lock();String stockObj = redisTemplate.opsForValue().get("STOCK_" + productId);// 从缓存中取if (Objects.nonNull(stockObj)) {stock = Integer.parseInt(stockObj);} else { // 从数据库查询并放入缓存Response<Integer> response = productStoreClient.getStockById(productId);if (Objects.isNull(response)){throw new RuntimeException("查询商品库存失败!");}stock = response.getBody();redisTemplate.opsForValue().set("STOCK_" + productId, String.valueOf(stock));}} catch (Exception e){e.printStackTrace();} finally {rLock.unlock();}return stock;}/*** 更新DB,删除缓存* @param productId* @param num*/private void updateStock(Long productId, Integer num){RReadWriteLock rReadWriteLock = redissonClient.getReadWriteLock("READ_WRITE_STOCK_" + productId);RLock wLock = rReadWriteLock.writeLock();try {wLock.lock();Integer stock = this.getStockById(productId);if (stock > 0) {// 更新DBproductStoreClient.updateStockById(productId, num);// 删除缓存redisTemplate.delete("STOCK_" + productId);System.out.println(Thread.currentThread().getName() + ",抢到券了");}} finally {wLock.unlock();}}
}
@GetMapping("/dealCoupon")public Response dealCoupon(){// 100个人抢三张券,每人限购一张for (int i = 0; i < 100; i++) {new Thread(()->{couponService.dealCoupon(1L, 1);}).start();}return Response.ok();}

http://www.lryc.cn/news/626073.html

相关文章:

  • 怎样平衡NLP技术发展中数据质量和隐私保护的关系?
  • JVM 面试精选 20 题(续)
  • JVM对象创建和内存分配
  • SpringAI接入openAI配置出现的问题全解析
  • 今日行情明日机会——20250819
  • Java开发面试实战:Spring Boot微服务与数据库优化案例分析
  • 星图云开发者平台新功能速递 | 微服务管理器:无缝整合异构服务,释放云原生开发潜能
  • 微服务如何集成swagger3
  • 微服务-08.微服务拆分-拆分商品服务
  • UE5 使用RVT制作地形材质融合
  • idea如何设置tab为4个空格
  • CSS backdrop-filter:给元素背景添加模糊与色调的高级滤镜
  • Day08 Go语言学习
  • Ansible 中的文件包含与导入机制
  • 常见 GC 收集器与适用场景:从吞吐量到亚毫秒停顿的全景指南
  • NestJS 依赖注入方式全解
  • TDengine IDMP 运维指南(3. 使用 Ansible 部署)
  • 【上升跟庄买入】副图/选股指标,动态黄色线由下向上穿越绿色基准线时,发出买入信号
  • day32-进程与线程(5)
  • Ubuntu 下面安装搜狗输入法debug记录
  • Ubuntu一键安装harbor脚本
  • WSL虚拟机(我的是ubuntu20.04)将系统文件转移到E盘
  • 机器学习之决策树:从原理到实战(附泰坦尼克号预测任务)
  • LINUX819 shell:for for,shift ,{} ,array[0] array[s] ,declare -x -a
  • 中科米堆CASAIM提供机加工件来料自动化测量尺寸方案
  • 中国互联网医院行业分析
  • Linux下Mysql命令,创建mysql,删除mysql
  • 基于多级缓存架构的Redis集群与Caffeine本地缓存实战经验分享
  • 原牛:一站式自媒体工具平台
  • 【LeetCode题解】LeetCode 153. 寻找旋转排序数组中的最小值