Redis實(shí)現(xiàn)限量?jī)?yōu)惠券的秒殺功能
核心:避免超賣(mài)問(wèn)題,保證一人一單 業(yè)務(wù)邏輯

代碼步驟分析

全部代碼
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {
@Resource
private ISeckillVoucherService seckillVoucherService;
@Resource
private RedisIdWorker redisIdWorker;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private RedissonClient redissonClient;
@Override
public Result seckillVoucher(Long voucherId) {
//1 查詢(xún)優(yōu)惠券信息
SeckillVoucher seckillVoucher = seckillVoucherService.getById(voucherId);
//2 判斷秒殺是否開(kāi)始
LocalDateTime now = LocalDateTime.now(); //現(xiàn)在時(shí)間
LocalDateTime beginTime = seckillVoucher.getBeginTime(); //開(kāi)始時(shí)間
LocalDateTime endTime = seckillVoucher.getEndTime(); //結(jié)束時(shí)間
if (now.isBefore(beginTime)) {
return Result.fail("秒殺還未開(kāi)始");
}
//3 判斷秒殺是否結(jié)束
if (now.isAfter(endTime)) {
return Result.fail("秒殺已結(jié)束");
}
//4 判斷庫(kù)存是否充足
int stock = (int) seckillVoucher.getStock();
if (stock == 0 && stock <= 0) {
return Result.fail("庫(kù)存不足");
}
//確保一人一單 用戶(hù)ID和代金券ID聯(lián)合查詢(xún)
Long userId = UserHolder.getUser().getId();
//先獲取鎖 再提交事務(wù)
//synchronized (userId.toString().intern()) {
//創(chuàng)建鎖對(duì)象
//SimpleRedisLock simpleRedisLock = new SimpleRedisLock("order:" + userId, stringRedisTemplate);
RLock lock = redissonClient.getLock("lock:order:" + userId);
//獲取鎖
boolean isLock = lock.tryLock();
//判斷是否獲取鎖成功
if (!isLock){
//獲取鎖失敗 返回錯(cuò)誤或失敗
return Result.fail("不允許重復(fù)下單");
}
try {
//獲取事務(wù)的代理對(duì)象
IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
return proxy.creatVoucherOrder(voucherId);
} finally {
//釋放鎖
lock.unlock();
}
//}//事務(wù)提交之后在釋放鎖
}
/**
* 這里對(duì)于加鎖做出一些解釋?zhuān)喝绻i加在整個(gè)方法上,那么就會(huì)導(dǎo)
* 致鎖的粒度過(guò)大,導(dǎo)致每個(gè)進(jìn)程進(jìn)來(lái)都會(huì)鎖住,所以要控制鎖的粒度
*/
@Transactional
public Result creatVoucherOrder(Long voucherId) {
Long userId = UserHolder.getUser().getId();
Integer count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();
if (count > 0) {
return Result.fail("用戶(hù)已經(jīng)購(gòu)買(mǎi)過(guò)了");
}
//5 扣減庫(kù)存-
boolean success = seckillVoucherService.update()
.setSql("stock = stock -1 ") //樂(lè)觀鎖
.eq("voucher_id", voucherId).gt("stock", 0) //判斷庫(kù)存是否大于0: where id = ? and stock > 0
.update();
if (!success) {
return Result.fail("庫(kù)存不足");
}
//6 創(chuàng)建訂單
//6.1 訂單ID
VoucherOrder voucherOrder = new VoucherOrder();
long orderid = RedisIdWorker.nextId("order");
voucherOrder.setVoucherId(orderid);
//6.2 用戶(hù)ID
voucherOrder.setUserId(userId);
//6.3 代金券ID
voucherOrder.setVoucherId(voucherId);
save(voucherOrder);
//7 返回訂單id
return Result.ok(orderid);
}
}到此這篇關(guān)于Redis實(shí)現(xiàn)限量?jī)?yōu)惠券的秒殺功能的文章就介紹到這了,更多相關(guān)Redis優(yōu)惠券秒殺內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis實(shí)現(xiàn)分布式鎖和等待序列的方法示例
這篇文章主要介紹了Redis實(shí)現(xiàn)分布式鎖和等待序列的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-06-06
虛擬機(jī)下的Redis無(wú)法訪問(wèn)報(bào)錯(cuò)500解決方法
這篇文章主要介紹了虛擬機(jī)下的Redis無(wú)法訪問(wèn),報(bào)錯(cuò)500解決方法,由于我的redis是在虛擬機(jī)下安裝的,無(wú)法訪問(wèn)redis的原因是因?yàn)樘摂M機(jī)的ip地址和主機(jī)不同,文中通過(guò)圖文結(jié)合給出了詳細(xì)的解決方法,需要的朋友可以參考下2024-02-02
淺談Redis位圖(Bitmap)及Redis二進(jìn)制中的問(wèn)題
這篇文章主要介紹了Redis位圖(Bitmap)及Redis二進(jìn)制中的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
Redis連接池監(jiān)控(連接池是否已滿)與優(yōu)化方法
本文詳細(xì)講解了如何在Linux系統(tǒng)中監(jiān)控Redis連接池的使用情況,以及如何通過(guò)連接池參數(shù)配置、系統(tǒng)資源使用情況、Redis命令監(jiān)控、外部監(jiān)控工具等多種方法進(jìn)行檢測(cè)和優(yōu)化,以確保系統(tǒng)在高并發(fā)場(chǎng)景下的性能和穩(wěn)定性,討論了連接池的概念、工作原理、參數(shù)配置,以及優(yōu)化策略等內(nèi)容2024-09-09
使用Redis實(shí)現(xiàn)點(diǎn)贊取消點(diǎn)贊的詳細(xì)代碼
這篇文章主要介紹了Redis實(shí)現(xiàn)點(diǎn)贊取消點(diǎn)贊的詳細(xì)代碼,通過(guò)查詢(xún)某實(shí)體(帖子、評(píng)論等)點(diǎn)贊數(shù)量,需要用到事務(wù)相關(guān)知識(shí),結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03
redis客戶(hù)端實(shí)現(xiàn)高可用讀寫(xiě)分離的方式詳解
基于sentienl 獲取和動(dòng)態(tài)感知 master、slaves節(jié)點(diǎn)信息的變化,我們的讀寫(xiě)分離客戶(hù)端就能具備高可用+動(dòng)態(tài)擴(kuò)容感知能力了,接下來(lái)通過(guò)本文給大家分享redis客戶(hù)端實(shí)現(xiàn)高可用讀寫(xiě)分離的方式,感興趣的朋友一起看看吧2021-07-07

