当前位置: 首页 > 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.dtcms.com/a/340069.html

相关文章:

  • Hive 存储管理测试用例设计指南
  • 力扣(最小栈)
  • Android逆向工程:Smali语法解析完整指南
  • [ Maven 开发工具 ] 环境搭建及配置
  • DRM驱动架构浅析-上(DRM基础概要与U-Boot阶段驱动解析)
  • 基于 OpenMV 的矩形识别与 STM32 串口通信(电子设计大赛实用教程)
  • k8s运维实践:高可用Redis Cluster(三主三从)与Proxy部署方案
  • 使用 Docker 安装长安链管理平台 + 部署区块链与示例合约
  • daily notes[3]
  • Eigen中Dense 模块简要介绍和实战应用示例(最小二乘拟合直线、协方差矩阵计算和稀疏求解等)
  • 三极管驱动led灯搭配的电阻选取方法
  • 跟随广州AI导游深度探寻广州历史底蕴​
  • 如何做一次AIMD
  • 农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
  • [OWASP]智能体应用安全保障指南
  • 英伟达显卡驱动怎么更新 详细步骤教程
  • MySQL练习题50题(附带详细教程)
  • Day13_【DataFrame数据组合concat连接】【案例】
  • C5.5:VDB及后面的电路讨论
  • 决策树(2)
  • Yum使用时报错
  • Spring Boot 全局异常处理
  • 快速了解Anaconda系统
  • 08.5【C++ 初阶】实现一个相对完整的日期类--附带源码
  • implement libtime on Windows
  • MyCAT基础概念
  • Python函数总结
  • week2-[一维数组]最大元素
  • 单细胞格式转换 rds 转成 h5ad
  • transformer模型初理解