Redis實現(xiàn)限量優(yōu)惠券的秒殺功能
更新時間:2024年12月03日 10:18:25 作者:mxbb.
文章詳細分析了避免超賣問題的方法,包括確保一人一單的業(yè)務(wù)邏輯,并提供了代碼實現(xià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 查詢優(yōu)惠券信息 SeckillVoucher seckillVoucher = seckillVoucherService.getById(voucherId); //2 判斷秒殺是否開始 LocalDateTime now = LocalDateTime.now(); //現(xiàn)在時間 LocalDateTime beginTime = seckillVoucher.getBeginTime(); //開始時間 LocalDateTime endTime = seckillVoucher.getEndTime(); //結(jié)束時間 if (now.isBefore(beginTime)) { return Result.fail("秒殺還未開始"); } //3 判斷秒殺是否結(jié)束 if (now.isAfter(endTime)) { return Result.fail("秒殺已結(jié)束"); } //4 判斷庫存是否充足 int stock = (int) seckillVoucher.getStock(); if (stock == 0 && stock <= 0) { return Result.fail("庫存不足"); } //確保一人一單 用戶ID和代金券ID聯(lián)合查詢 Long userId = UserHolder.getUser().getId(); //先獲取鎖 再提交事務(wù) //synchronized (userId.toString().intern()) { //創(chuàng)建鎖對象 //SimpleRedisLock simpleRedisLock = new SimpleRedisLock("order:" + userId, stringRedisTemplate); RLock lock = redissonClient.getLock("lock:order:" + userId); //獲取鎖 boolean isLock = lock.tryLock(); //判斷是否獲取鎖成功 if (!isLock){ //獲取鎖失敗 返回錯誤或失敗 return Result.fail("不允許重復(fù)下單"); } try { //獲取事務(wù)的代理對象 IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy(); return proxy.creatVoucherOrder(voucherId); } finally { //釋放鎖 lock.unlock(); } //}//事務(wù)提交之后在釋放鎖 } /** * 這里對于加鎖做出一些解釋:如果鎖加在整個方法上,那么就會導(dǎo) * 致鎖的粒度過大,導(dǎo)致每個進程進來都會鎖住,所以要控制鎖的粒度 */ @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("用戶已經(jīng)購買過了"); } //5 扣減庫存- boolean success = seckillVoucherService.update() .setSql("stock = stock -1 ") //樂觀鎖 .eq("voucher_id", voucherId).gt("stock", 0) //判斷庫存是否大于0: where id = ? and stock > 0 .update(); if (!success) { return Result.fail("庫存不足"); } //6 創(chuàng)建訂單 //6.1 訂單ID VoucherOrder voucherOrder = new VoucherOrder(); long orderid = RedisIdWorker.nextId("order"); voucherOrder.setVoucherId(orderid); //6.2 用戶ID voucherOrder.setUserId(userId); //6.3 代金券ID voucherOrder.setVoucherId(voucherId); save(voucherOrder); //7 返回訂單id return Result.ok(orderid); } }
到此這篇關(guān)于Redis實現(xiàn)限量優(yōu)惠券的秒殺功能的文章就介紹到這了,更多相關(guān)Redis優(yōu)惠券秒殺內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Redis位圖(Bitmap)及Redis二進制中的問題
這篇文章主要介紹了Redis位圖(Bitmap)及Redis二進制中的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07Redis連接池監(jiān)控(連接池是否已滿)與優(yōu)化方法
本文詳細講解了如何在Linux系統(tǒng)中監(jiān)控Redis連接池的使用情況,以及如何通過連接池參數(shù)配置、系統(tǒng)資源使用情況、Redis命令監(jiān)控、外部監(jiān)控工具等多種方法進行檢測和優(yōu)化,以確保系統(tǒng)在高并發(fā)場景下的性能和穩(wěn)定性,討論了連接池的概念、工作原理、參數(shù)配置,以及優(yōu)化策略等內(nèi)容2024-09-09