第一种:使用synchronized(只适用于单个tomcat)

@Autowired
private StringRedisTemplate stringRedisTemplate;
@GetMapping("/deduct")public String toDeduct(){synchronized (this) {int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));if (stock > 0) {Long stock1 = stringRedisTemplate.opsForValue().decrement("stock");System.out.println("扣减成功,剩余库存:" + stock1);}else{System.out.println("扣减失败,库存不足");}return "end";}}

第二种:使用SETNX命令(多台tomcat)

 @GetMapping("/deduct_stock")public String deductStock() throws InterruptedException {String lockKey = "lockKey";//设计唯一key值防止锁失效问题String clientId = UUID.randomUUID().toString();//设计锁超时时间,防止服务器宕机时锁没有释放掉(finally语句没有执行)Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 10, TimeUnit.SECONDS);//jedis.setnx(key,value);//若键 key 已经存在, 则 SETNX 命令不做任何动作。result==falseif (!result) {return "正在排队。。。";}try {int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));if (stock > 0) {Long realStock = stringRedisTemplate.opsForValue().decrement("stock");System.out.println("扣减成功,剩余库存:" + realStock);}else{System.out.println("扣减失败,库存不足");}} finally {//防止锁失效问题,在多线程的情况下,每个线程只释放自己创建的锁,线程之间互不干预。if(clientId.equals(stringRedisTemplate.opsForValue().get(lockKey))) {stringRedisTemplate.delete(lockKey);}}return "end";}

第三种:使用Redission框架(原理跟第二种一样)

1、配置config类

@Configuration
public class RedissonConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private String port;@Value("${spring.redis.password}")private String password;@Beanpublic RedissonClient getRedisson(){Config config = new Config();config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);//添加主从配置
//      config.useMasterSlaveServers().setMasterAddress("").setPassword("").addSlaveAddress(new String[]{"",""});return Redisson.create(config);}
}
@GetMapping("/deduct_stock1")public String deductStock1(){String lockKey = "lockKey";RLock redissonLock = redisson.getLock(lockKey);try {redissonLock.lock();int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));if (stock > 0) {Long realStock = stringRedisTemplate.opsForValue().decrement("stock");System.out.println("扣减成功,剩余库存:" + realStock);}else{System.out.println("扣减失败,库存不足");}} finally {redissonLock.unlock();}return "end";}

Redission原理:

Redission使用了Lua 脚本,实现原理跟原理跟第二种差不多。
当业务代码处理时间很长,像mysql慢查询等等,可以在try代码块中每隔10秒检查是否还持有锁,如果持有则延长锁的时间,防止还没执行完业务代码“lockKey”就到了失效时间。


测试环境搭建

Redis命令大全

设置Redis密码

pom:

     <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.5.7</version></dependency>

application.properties:

server.port=8090
# redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=888888
spring.redis.jedis.pool.max-active=500
spring.redis.jedis.pool.max-idle=1000
spring.redis.jedis.pool.max-wait=6000ms
spring.redis.jedis.pool.min-idle=4

Nginx负载均衡:

 upstream redislock{server 127.0.0.1:8080 weight = 1;server 127.0.0.1:8090 weight = 1;}server {listen       80;server_name  localhost;location / {root html;index index.html index.htm;proxy_pass http://redislock;}}

Jmeter压力测试


发送http请求:

设置发送地址:

表示在0秒内发送200个请求,处理完后再发送200 * 3次,总计200 * 4次请求:

结果集:

测试结果:


没有出现超卖问题

解决Redis超卖问题相关推荐

  1. mysql乐观锁处理超卖_通过乐观锁解决库存超卖的问题

    前言 在通过多线程来解决高并发的问题上,线程安全往往是最先需要考虑的问题,其次才是性能.库存超卖问题是有很多种技术解决方案的,比如悲观锁,分布式锁,乐观锁,队列串行化,Redis原子操作等.本篇通过M ...

  2. java实现秒杀业务之解决秒杀超卖的问题

    第一步:在减少库存的时候进行判断stock_count>0 package com.jack.seckill.dao;@Mapper public interface GoodsDao {@Up ...

  3. redis如何解决秒杀超卖java_Spring Boot + redis解决商品秒杀库存超卖,看这篇文章就够了...

    作者:涛哥谈篮球 来源:toutiao.com/i6836611989607809548 问题描述 在众多抢购活动中,在有限的商品数量的限制下如何保证抢购到商品的用户数不能大于商品数量,也就是不能出现 ...

  4. php下用redis解决秒杀超卖问题

    秒杀超卖问题,就是有一个商品抢购活动,一个商品假如有100件库存,但是在抢购时有200人来抢购,这时就会并发,原本只有100的库存但是抢购的人过多,就会发生数据库里原本只有100的库存但是库存为0的时 ...

  5. Redis解决库存超卖问题,大厂直通车

    查询商品信息 (调用商品服务) 计算总价(生成订单详情) 商品服务扣库存(调用商品服务) 订单入库( 生成订单) // 原始的MySQL同步流程 // 判断此代金券是否加入抢购 SeckillVouc ...

  6. 阿里面试官:高并发大流量秒杀系统如何正确的解决库存超卖问题?(建议收藏)

    大家好,我是冰河~~ 在[精通高并发系列]的<实践出真知:全网最强秒杀系统架构解密!!>一文中,冰河详细的阐述了高并发秒杀系统的架构设计,也简单提到了如何扣减商品的库存. 也许不少小伙伴会 ...

  7. 秒杀场景_解决秒杀超卖问题_04

    文章目录 一.商品微服务改造 二.秒杀微服务改造 2.1. SkillGoodService 改造 2.2. MutilThreadOrder 改造 一.商品微服务改造 SkillGoodServic ...

  8. 超级简单方法解决秒杀超卖和重复购买问题

    一.基本原则 1.SQL加库存数量判断:防止库存变成负数 2..数据库加唯一索引:防止用户重复购买 二.举例说明 1.开启事务 2.商品表减库存,库存数量要大于0 update miaosha_goo ...

  9. 基于秒杀系统解决超卖、限流、Redis限时抢购等问题

    完整项目请见:https://gitee.com/JiaBin1 一.什么是秒杀 秒杀最直观的定义:在高并发场景下而下单某一个商品,这个过程就叫秒杀 [秒杀场景] 火车票抢票 双十一限购商品 热度高的 ...

最新文章

  1. 辍学的名人_我辍学去追求成为网络开发人员和设计师的梦想
  2. 《走进SAP(第2版)》——第2章 企业软件的SAP之路2.1 企业资源计划(ERP)...
  3. Beanstalkd工作队列
  4. SAP系统和微信集成的系列教程之四:如何将SAP C4C主数据变化推送给微信公众号的关注者
  5. android bitmap 加边框,Android 给圆角的Bitmap加边框
  6. 京东:网传通过 Bug 抢茅台是假消息;罗永浩回应带货价格非「全网最低」;Rust 文档团队解散 | 极客头条...
  7. 2021,软件测试的出路在哪里?
  8. Java IO流学习总结(1)
  9. ElasticSearch常用的几种查询方式
  10. wapp HTTP Error 404. The requested resource is not found.
  11. AdminLTE框架的基本使用
  12. 算法工程师面试基础题目及答案
  13. js存储数据cookie,localhost,sessionstorage
  14. 查看自己电脑的主板支持多大的内存
  15. STM32之TIM1高级定时器
  16. 【教程】小米手机Android 7.0+抓取HTTPS请求安装Charles证书主要流程
  17. Multi class ovr or ovo
  18. docx poi 原理_POI读取.doc 和.docx的区别
  19. 域名圈“巴菲特”戴跃:我认知不够,做了韭菜 | 《8问》
  20. 使用workbench导入excel中的数据

热门文章

  1. 如何规划自己的博士五年生活?
  2. 文巾解题 196. 删除重复的电子邮箱
  3. 文巾解题 67. 二进制求和
  4. 【数据可视化应用】绘制极坐标(附Python代码)
  5. RabbitMQ 还是 Kafka?哪个才是架构利器
  6. Linux疑难杂症解决方案100篇(十四)-Linux scp 使用详解
  7. 一块钱哪里去了?--java浮点型背后的故事
  8. spring data redis使用示例
  9. 子查询in和表连接效率
  10. 原来评分卡模型的概率是这么校准的!