文章目录
- 前言
- 一、超卖是什么?
- 二、实现步骤
- 1.引入依赖
- 2.代码实现
- 三、测试
- 1.使用测试工具测试
- 四、总结
前言
目前基本上的电商业务都会有购买商品多人同时购买或者秒杀业务场景,这里介绍在这种业务场景下如何防止出现商品超卖的现象。
一、超卖是什么?
当商品库存接近0时,此时多个买家同时下单付款购买同一商品,买家成功购买的商品数量大于商品库存数量,将会出现超卖现象,超卖现象本质上就是买到了比仓库中的数量更多的商品。
二、实现步骤
1.引入依赖
在 pom.xml 引入依赖
代码如下(示例):
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.10.6</version>
</dependency>
2.代码实现
2.1:yml配置:
spring:
#redis缓存配置
redis:
host: 127.0.0.1
port: 6379
password: 123456
timeout: 60000 #redis 连接超时时间ms
database: 11 #指定使用哪个reids库
2.2:创建RedissonUtils工具类
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @description :Redisson工具类
*/
@Component
public class RedissonUtils {
private static RedissonClient redissonClient;
@Autowired
public void setRedissonClient(RedissonClient redissonClient) {
RedissonUtils.redissonClient = redissonClient;
}
/**
* 加锁
* @param lockKey
* @return
*/
public RLock lock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock();
return lock;
}
/**
* 获取锁
* @param lockKey
* @return
*/
public RLock getLock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
return lock;
}
/**
* 释放锁
*
* @param lockKey
*/
public void unlock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
lock.unlock();
}
/**
* 释放锁
* @param lock
*/
public void unlock(RLock lock) {
lock.unlock();
}
/**
* 此方法是阻塞获取锁的方式,如果当前锁被其他线程持有,则当前线程会一直阻塞等待获取锁,直到获取到锁或者发生超时或中断等情况才会结束等待。该方法获取到锁之后可以保证线程对共享资源的访问是互斥的,
* 适用于需要确保共享资源只能被一个线程访问的场景。Redisson 的 lock() 方法支持可重入锁和公平锁等特性,
* 可以更好地满足多线程并发访问的需求。
*
* 带超时的锁
* @param lockKey
* @param timeout 超时时间 单位:秒
*/
public RLock lock(String lockKey, int timeout) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, TimeUnit.SECONDS);
return lock;
}
/**
* 此方法是阻塞获取锁的方式,如果当前锁被其他线程持有,则当前线程会一直阻塞等待获取锁,直到获取到锁或者发生超时或中断等情况才会结束等待。该方法获取到锁之后可以保证线程对共享资源的访问是互斥的,
* 适用于需要确保共享资源只能被一个线程访问的场景。Redisson 的 lock() 方法支持可重入锁和公平锁等特性,
* 可以更好地满足多线程并发访问的需求。
*
* 带超时的锁
* @param lockKey
* @param unit 时间单位
* @param timeout 超时时间
*/
public RLock lock(String lockKey, int timeout, TimeUnit unit) {
RLock lock = redissonClient.getLock(lockKey);
lock.lock(timeout, unit);
return lock;
}
/**
* 此方法是一种非阻塞获取锁的方式,在尝试获取锁时不会阻塞当前线程,而是立即返回获取锁的结果,如果获取成功则返回 true,
* 否则返回 false。Redisson 的 tryLock() 方法支持加锁时间限制、等待时间限制以及可重入等特性,
* 可以更好地控制获取锁的过程和等待时间,避免程序出现长时间无法响应等问题。
*
* 尝试获取锁
* @param lockKey
* @param waitTime 最多等待时间 单位:秒
* @param leaseTime 上锁后自动释放锁时间 单位:秒
* @return
*/
public boolean tryLock(String lockKey, int waitTime, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
return false;
}
}
/**
* 此方法是一种非阻塞获取锁的方式,在尝试获取锁时不会阻塞当前线程,而是立即返回获取锁的结果,如果获取成功则返回 true,
* 否则返回 false。Redisson 的 tryLock() 方法支持加锁时间限制、等待时间限制以及可重入等特性,
* 可以更好地控制获取锁的过程和等待时间,避免程序出现长时间无法响应等问题。
*
* 尝试获取锁
* @param lockKey
* @param unit 时间单位
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @return
*/
public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
RLock lock = redissonClient.getLock(lockKey);
try {
return lock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
}
}
2.3:业务代码
package com.absen.b2b.kaihuile.module.hotel.controller.platform.visitor;
import com.absen.b2b.kaihuile.common.base.KaiHuiLeApiResponse;
import com.absen.b2b.kaihuile.common.redis.utils.RedissonUtils;
import com.absen.b2b.kaihuile.module.hotel.controller.publics.visitor.PublicVisitorHallInquiryUserJoinController;
import com.absen.b2b.kaihuile.module.hotel.dto.QuoteBeforeHallContrastQueryDto;
import com.absen.b2b.kaihuile.module.hotel.entity.HallBiddingEntity;
import com.absen.b2b.kaihuile.module.hotel.entity.HallInquiryUserJoinEntity;
import com.absen.b2b.kaihuile.module.hotel.service.HallBiddingService;
import com.absen.b2b.kaihuile.module.hotel.service.InquiryCustomerArchivesService;
import com.absen.b2b.kaihuile.module.hotel.vo.QuoteBeforeHallContrastVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @Description: 测试下单减库存超卖
* @Author: rong.jiang
* @Date: 2023/6/16
*/
@RestController
@RequestMapping("platform/api/visitor/hall/userJoin")
public class PlatformVisitorHallInquiryUserJoinController extends PublicVisitorHallInquiryUserJoinController {
@Autowired
private RedissonUtils redissonUtils;
@Autowired
private HallBiddingService hallBiddingService;
/**
* 未使用加锁(出现超卖情况)
*
* @param goodsId 商品id
* @return
*/
@GetMapping(value = "/lock/chaomai/{goodsId}")
public KaiHuiLeApiResponse chaomai(@ApiParam(value = "商品id") @PathVariable(value = "goodsId") String goodsId) {
//商品信息
HallBiddingEntity hallBidding = hallBiddingService.getById(goodsId);
if (0 == hallBidding.getBoardNumber()) {
throw new RuntimeException("商品数量库存不足");
}
//1.创建业务订单数据逻辑,业务代码忽略
//2.扣减商品库存
hallBidding.setBoardNumber(hallBidding.getBoardNumber() - 1);
System.out.println("未使用加锁^^设置库存:" + hallBidding.getBoardNumber());
hallBiddingService.updateById(hallBidding);
return KaiHuiLeApiResponse.ok();
}
/**
* 使用加锁(防止超卖情况)
*
* @param goodsId 商品id
* @return
*/
@GetMapping(value = "/lock/nochaomai/{goodsId}")
public KaiHuiLeApiResponse nochaomai(@ApiParam(value = "商品id") @PathVariable(value = "goodsId") String goodsId) {
Boolean locked = false;
try {
//加锁,设置锁超时时间(120秒),等待锁的时间(10秒)
locked = redissonUtils.tryLock(goodsId, 120, 10);
if (!locked) {
return KaiHuiLeApiResponse.fail("当前商品库存有其他订单在操作");
}
//商品信息
HallBiddingEntity hallBidding = hallBiddingService.getById(goodsId);
if (0 == hallBidding.getBoardNumber()) {
throw new RuntimeException("商品数量库存不足");
}
//1.创建业务订单数据逻辑,业务代码忽略
//2.扣减商品库存
hallBidding.setBoardNumber(hallBidding.getBoardNumber() - 1);
System.out.println("使用加锁^^设置库存:" + hallBidding.getBoardNumber());
hallBiddingService.updateById(hallBidding);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (locked) {
redissonUtils.unlock(goodsId);
}
}
return KaiHuiLeApiResponse.ok();
}
}
三、测试
1.使用测试工具测试
本例使用的是Apipost工具
测试工具下载地址:https://www.apipost.cn/download.html
1.1:测试:超卖情况
初始化数据库商品库存为50
并发数为100,100个用户同时下单模拟
控制台输出结果:输出显示一个商品都被卖了多次情况
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
2023-08-12 11:09:52.574 b2b-kaihuile-logback http-nio-5000-exec-52 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
2023-08-12 11:09:52.574 b2b-kaihuile-logback http-nio-5000-exec-19 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
2023-08-12 11:09:52.574 b2b-kaihuile-logback http-nio-5000-exec-94 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
未使用加锁^^设置库存:49
数据库库存变化结果:初始化50,执行后没有将库存清空,正常情况100人同时下单库存会被抢完
1.2:测试:防止超卖情况
初始化数据库商品库存为50
并发数为100,100个用户同时下单模拟
控制台输出结果:输出显示未出现超卖情况
使用加锁^^设置库存:49
2023-08-12 11:29:42.695 b2b-kaihuile-logback http-nio-5000-exec-183 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Preparing: UPDATE hms_hall_bidding SET inquiry_detail_id=?, inquiry_id=?, corresponding_period=?, active_time=?, big_bed_number=?, double_bed_number=?, board_number=?, latest_time=?, active_type=?, previously_used_hotel=?, accommodation_budget=?, other=?, creator_id=?, creator_name=?, creator_time=?, editor_id=?, editor_name=?, editor_time=? WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.696 b2b-kaihuile-logback http-nio-5000-exec-183 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Parameters: (String), (String), (String), 2023-07-20 00:00:00.0(Timestamp), 0(Integer), 0(Integer), 49(Integer), 2023-07-19 00:00:00.0(Timestamp), 0(Integer), 无(String), 200(Integer), 祝你新年快乐了(String), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-07-04 14:47:35.0(Timestamp), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-08-12 11:29:42.694(Timestamp), 1001(String)
2023-08-12 11:29:42.701 b2b-kaihuile-logback http-nio-5000-exec-183 DEBUG c.a.b.k.m.h.m.H.updateById - <== Updates: 1
2023-08-12 11:29:42.706 b2b-kaihuile-logback http-nio-5000-exec-167 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Preparing: SELECT hall_bidding_id,inquiry_detail_id,inquiry_id,corresponding_period,active_time,big_bed_number,double_bed_number,board_number,latest_time,active_type,previously_used_hotel,accommodation_budget,other,is_delete,creator_id,creator_name,creator_time,editor_id,editor_name,editor_time FROM hms_hall_bidding WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.706 b2b-kaihuile-logback http-nio-5000-exec-167 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
2023-08-12 11:29:42.708 b2b-kaihuile-logback http-nio-5000-exec-167 DEBUG c.a.b.k.m.h.m.H.selectById - <== Total: 1
使用加锁^^设置库存:48
2023-08-12 11:29:42.709 b2b-kaihuile-logback http-nio-5000-exec-167 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Preparing: UPDATE hms_hall_bidding SET inquiry_detail_id=?, inquiry_id=?, corresponding_period=?, active_time=?, big_bed_number=?, double_bed_number=?, board_number=?, latest_time=?, active_type=?, previously_used_hotel=?, accommodation_budget=?, other=?, creator_id=?, creator_name=?, creator_time=?, editor_id=?, editor_name=?, editor_time=? WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.710 b2b-kaihuile-logback http-nio-5000-exec-167 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Parameters: (String), (String), (String), 2023-07-20 00:00:00.0(Timestamp), 0(Integer), 0(Integer), 48(Integer), 2023-07-19 00:00:00.0(Timestamp), 0(Integer), 无(String), 200(Integer), 祝你新年快乐了(String), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-07-04 14:47:35.0(Timestamp), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-08-12 11:29:42.709(Timestamp), 1001(String)
2023-08-12 11:29:42.715 b2b-kaihuile-logback http-nio-5000-exec-167 DEBUG c.a.b.k.m.h.m.H.updateById - <== Updates: 1
2023-08-12 11:29:42.719 b2b-kaihuile-logback http-nio-5000-exec-125 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Preparing: SELECT hall_bidding_id,inquiry_detail_id,inquiry_id,corresponding_period,active_time,big_bed_number,double_bed_number,board_number,latest_time,active_type,previously_used_hotel,accommodation_budget,other,is_delete,creator_id,creator_name,creator_time,editor_id,editor_name,editor_time FROM hms_hall_bidding WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.719 b2b-kaihuile-logback http-nio-5000-exec-125 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
2023-08-12 11:29:42.723 b2b-kaihuile-logback http-nio-5000-exec-125 DEBUG c.a.b.k.m.h.m.H.selectById - <== Total: 1
使用加锁^^设置库存:47
2023-08-12 11:29:42.724 b2b-kaihuile-logback http-nio-5000-exec-125 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Preparing: UPDATE hms_hall_bidding SET inquiry_detail_id=?, inquiry_id=?, corresponding_period=?, active_time=?, big_bed_number=?, double_bed_number=?, board_number=?, latest_time=?, active_type=?, previously_used_hotel=?, accommodation_budget=?, other=?, creator_id=?, creator_name=?, creator_time=?, editor_id=?, editor_name=?, editor_time=? WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.724 b2b-kaihuile-logback http-nio-5000-exec-125 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Parameters: (String), (String), (String), 2023-07-20 00:00:00.0(Timestamp), 0(Integer), 0(Integer), 47(Integer), 2023-07-19 00:00:00.0(Timestamp), 0(Integer), 无(String), 200(Integer), 祝你新年快乐了(String), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-07-04 14:47:35.0(Timestamp), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-08-12 11:29:42.723(Timestamp), 1001(String)
2023-08-12 11:29:42.727 b2b-kaihuile-logback http-nio-5000-exec-125 DEBUG c.a.b.k.m.h.m.H.updateById - <== Updates: 1
2023-08-12 11:29:42.731 b2b-kaihuile-logback http-nio-5000-exec-141 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Preparing: SELECT hall_bidding_id,inquiry_detail_id,inquiry_id,corresponding_period,active_time,big_bed_number,double_bed_number,board_number,latest_time,active_type,previously_used_hotel,accommodation_budget,other,is_delete,creator_id,creator_name,creator_time,editor_id,editor_name,editor_time FROM hms_hall_bidding WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.732 b2b-kaihuile-logback http-nio-5000-exec-141 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
2023-08-12 11:29:42.734 b2b-kaihuile-logback http-nio-5000-exec-141 DEBUG c.a.b.k.m.h.m.H.selectById - <== Total: 1
使用加锁^^设置库存:46
2023-08-12 11:29:42.735 b2b-kaihuile-logback http-nio-5000-exec-141 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Preparing: UPDATE hms_hall_bidding SET inquiry_detail_id=?, inquiry_id=?, corresponding_period=?, active_time=?, big_bed_number=?, double_bed_number=?, board_number=?, latest_time=?, active_type=?, previously_used_hotel=?, accommodation_budget=?, other=?, creator_id=?, creator_name=?, creator_time=?, editor_id=?, editor_name=?, editor_time=? WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.736 b2b-kaihuile-logback http-nio-5000-exec-141 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Parameters: (String), (String), (String), 2023-07-20 00:00:00.0(Timestamp), 0(Integer), 0(Integer), 46(Integer), 2023-07-19 00:00:00.0(Timestamp), 0(Integer), 无(String), 200(Integer), 祝你新年快乐了(String), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-07-04 14:47:35.0(Timestamp), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-08-12 11:29:42.735(Timestamp), 1001(String)
2023-08-12 11:29:42.739 b2b-kaihuile-logback http-nio-5000-exec-141 DEBUG c.a.b.k.m.h.m.H.updateById - <== Updates: 1
2023-08-12 11:29:42.742 b2b-kaihuile-logback http-nio-5000-exec-172 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Preparing: SELECT hall_bidding_id,inquiry_detail_id,inquiry_id,corresponding_period,active_time,big_bed_number,double_bed_number,board_number,latest_time,active_type,previously_used_hotel,accommodation_budget,other,is_delete,creator_id,creator_name,creator_time,editor_id,editor_name,editor_time FROM hms_hall_bidding WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.743 b2b-kaihuile-logback http-nio-5000-exec-172 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
2023-08-12 11:29:42.744 b2b-kaihuile-logback http-nio-5000-exec-172 DEBUG c.a.b.k.m.h.m.H.selectById - <== Total: 1
使用加锁^^设置库存:45
2023-08-12 11:29:42.745 b2b-kaihuile-logback http-nio-5000-exec-172 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Preparing: UPDATE hms_hall_bidding SET inquiry_detail_id=?, inquiry_id=?, corresponding_period=?, active_time=?, big_bed_number=?, double_bed_number=?, board_number=?, latest_time=?, active_type=?, previously_used_hotel=?, accommodation_budget=?, other=?, creator_id=?, creator_name=?, creator_time=?, editor_id=?, editor_name=?, editor_time=? WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.746 b2b-kaihuile-logback http-nio-5000-exec-172 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Parameters: (String), (String), (String), 2023-07-20 00:00:00.0(Timestamp), 0(Integer), 0(Integer), 45(Integer), 2023-07-19 00:00:00.0(Timestamp), 0(Integer), 无(String), 200(Integer), 祝你新年快乐了(String), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-07-04 14:47:35.0(Timestamp), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-08-12 11:29:42.745(Timestamp), 1001(String)
2023-08-12 11:29:42.749 b2b-kaihuile-logback http-nio-5000-exec-172 DEBUG c.a.b.k.m.h.m.H.updateById - <== Updates: 1
2023-08-12 11:29:42.752 b2b-kaihuile-logback http-nio-5000-exec-177 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Preparing: SELECT hall_bidding_id,inquiry_detail_id,inquiry_id,corresponding_period,active_time,big_bed_number,double_bed_number,board_number,latest_time,active_type,previously_used_hotel,accommodation_budget,other,is_delete,creator_id,creator_name,creator_time,editor_id,editor_name,editor_time FROM hms_hall_bidding WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.753 b2b-kaihuile-logback http-nio-5000-exec-177 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
2023-08-12 11:29:42.755 b2b-kaihuile-logback http-nio-5000-exec-177 DEBUG c.a.b.k.m.h.m.H.selectById - <== Total: 1
使用加锁^^设置库存:44
2023-08-12 11:29:42.756 b2b-kaihuile-logback http-nio-5000-exec-177 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Preparing: UPDATE hms_hall_bidding SET inquiry_detail_id=?, inquiry_id=?, corresponding_period=?, active_time=?, big_bed_number=?, double_bed_number=?, board_number=?, latest_time=?, active_type=?, previously_used_hotel=?, accommodation_budget=?, other=?, creator_id=?, creator_name=?, creator_time=?, editor_id=?, editor_name=?, editor_time=? WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.756 b2b-kaihuile-logback http-nio-5000-exec-177 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Parameters: (String), (String), (String), 2023-07-20 00:00:00.0(Timestamp), 0(Integer), 0(Integer), 44(Integer), 2023-07-19 00:00:00.0(Timestamp), 0(Integer), 无(String), 200(Integer), 祝你新年快乐了(String), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-07-04 14:47:35.0(Timestamp), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-08-12 11:29:42.755(Timestamp), 1001(String)
2023-08-12 11:29:42.758 b2b-kaihuile-logback http-nio-5000-exec-177 DEBUG c.a.b.k.m.h.m.H.updateById - <== Updates: 1
2023-08-12 11:29:42.762 b2b-kaihuile-logback http-nio-5000-exec-165 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Preparing: SELECT hall_bidding_id,inquiry_detail_id,inquiry_id,corresponding_period,active_time,big_bed_number,double_bed_number,board_number,latest_time,active_type,previously_used_hotel,accommodation_budget,other,is_delete,creator_id,creator_name,creator_time,editor_id,editor_name,editor_time FROM hms_hall_bidding WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.762 b2b-kaihuile-logback http-nio-5000-exec-165 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
2023-08-12 11:29:42.764 b2b-kaihuile-logback http-nio-5000-exec-165 DEBUG c.a.b.k.m.h.m.H.selectById - <== Total: 1
使用加锁^^设置库存:43
2023-08-12 11:29:42.766 b2b-kaihuile-logback http-nio-5000-exec-165 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Preparing: UPDATE hms_hall_bidding SET inquiry_detail_id=?, inquiry_id=?, corresponding_period=?, active_time=?, big_bed_number=?, double_bed_number=?, board_number=?, latest_time=?, active_type=?, previously_used_hotel=?, accommodation_budget=?, other=?, creator_id=?, creator_name=?, creator_time=?, editor_id=?, editor_name=?, editor_time=? WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.767 b2b-kaihuile-logback http-nio-5000-exec-165 DEBUG c.a.b.k.m.h.m.H.updateById - ==> Parameters: (String), (String), (String), 2023-07-20 00:00:00.0(Timestamp), 0(Integer), 0(Integer), 43(Integer), 2023-07-19 00:00:00.0(Timestamp), 0(Integer), 无(String), 200(Integer), 祝你新年快乐了(String), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-07-04 14:47:35.0(Timestamp), cf68f402eef7ca15a29142a8bc944e4f(String), 应俊(String), 2023-08-12 11:29:42.766(Timestamp), 1001(String)
2023-08-12 11:29:42.769 b2b-kaihuile-logback http-nio-5000-exec-165 DEBUG c.a.b.k.m.h.m.H.updateById - <== Updates: 1
2023-08-12 11:29:42.773 b2b-kaihuile-logback http-nio-5000-exec-38 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Preparing: SELECT hall_bidding_id,inquiry_detail_id,inquiry_id,corresponding_period,active_time,big_bed_number,double_bed_number,board_number,latest_time,active_type,previously_used_hotel,accommodation_budget,other,is_delete,creator_id,creator_name,creator_time,editor_id,editor_name,editor_time FROM hms_hall_bidding WHERE hall_bidding_id=? AND is_delete=0
2023-08-12 11:29:42.773 b2b-kaihuile-logback http-nio-5000-exec-38 DEBUG c.a.b.k.m.h.m.H.selectById - ==> Parameters: 1001(String)
2023-08-12 11:29:42.775 b2b-kaihuile-logback http-nio-5000-exec-38 DEBUG c.a.b.k.m.h.m.H.selectById - <== Total: 1
使用加锁^^设置库存:42
数据库库存变化结果:初始化50,执行后库存被清空,库存已被抢完
四、总结
-
使用redisson
实现,能够保证多实例下线程安全,代码简单可靠