明日方舟正版最新版
1.85GB · 2025-09-26
在集群下的并发问题:
业务流程:
具体实现:
ILock
package com.hmdp.utils;public interface ILock { // 获取锁 boolean tryLock(long timeoutSec); // 释放锁 void unlock();}
SimpleRedisLock
package com.hmdp.utils;import org.springframework.data.redis.core.StringRedisTemplate;import java.util.concurrent.TimeUnit;public class SimpleRedisLock implements ILock { private String name; private StringRedisTemplate stringRedisTemplate; private static final String KEY_PREFIX = "lock:"; public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) { this.name = name; this.stringRedisTemplate = stringRedisTemplate; } @Override public boolean tryLock(long timeoutSec) { // 获取线程的标识 long threadId = Thread.currentThread().getId(); // 获取锁 Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId + "", timeoutSec, TimeUnit.SECONDS); return Boolean.TRUE.equals(success); } @Override public void unlock() { // 释放锁 stringRedisTemplate.delete(KEY_PREFIX + name); }}
VoucherOrderServiceImpl
package com.hmdp.service.impl;import com.hmdp.dto.Result;import com.hmdp.entity.SeckillVoucher;import com.hmdp.entity.VoucherOrder;import com.hmdp.mapper.VoucherOrderMapper;import com.hmdp.service.ISeckillVoucherService;import com.hmdp.service.IVoucherOrderService;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.hmdp.utils.RedisIdWorker;import com.hmdp.utils.SimpleRedisLock;import com.hmdp.utils.UserHolder;import org.springframework.aop.framework.AopContext;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;import java.time.LocalDateTime;/** * <p> * 服务实现类 * </p> * * @author ztn * @since 2025-09-23 */@Servicepublic class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService { @Resource private ISeckillVoucherService seckillVoucherService; @Resource private RedisIdWorker redisIdWorker; @Resource private StringRedisTemplate stringRedisTemplate; @Override public Result seckillVocher(Long voucherId) { // 1.查询优惠券 SeckillVoucher voucher = seckillVoucherService.getById(voucherId); // 2.判断秒杀是否开始 if(voucher.getBeginTime().isAfter(LocalDateTime.now())){ return Result.fail("秒杀尚未开始"); } // 3.判断秒杀是否结束 if(voucher.getEndTime().isBefore(LocalDateTime.now())){ return Result.fail("秒杀已经结束"); } // 4.判断库是否充足 if(voucher.getStock() < 1){ return Result.fail("库存不足"); } Long userId = UserHolder.getUser().getId(); // 创建锁对象 SimpleRedisLock lock = new SimpleRedisLock("order:" + userId, stringRedisTemplate); // 获取锁 boolean isLock = lock.tryLock(1200); // 判断是否获取锁成功 if(!isLock){ // 获取锁失败,返回错误或重试 return Result.fail("不允许重复下单"); } try { // 获取代理对象(事务) IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy(); return proxy.createVoucherOrder(voucherId); }finally { // 释放锁 lock.unlock(); } } @Transactional public Result createVoucherOrder(Long voucherId) { // 5.一人一单 Long userId = UserHolder.getUser().getId(); // 5.1 查询订单 int count = query().eq("user_id", userId).eq("voucher_id", voucherId).count(); // 5.2 判断是否存在 if(count > 0){ // 用户已经购买过了 return Result.fail("用户已经购买过一次了"); } // 6.扣减库存 boolean success = seckillVoucherService.update() .setSql("stock = stock - 1") // set stock =stock -1 .eq("voucher_id", voucherId)// .eq("stock",voucher.getStock()) // where id = ? and stock = ? .gt("stock",0) // where id = ? and stock > 0 .update(); if(!success){ return Result.fail("库存不足"); } // 7.创建订单 VoucherOrder voucherOrder = new VoucherOrder(); // 7.1订单id long orderId = redisIdWorker.nextId("order"); voucherOrder.setId(orderId); // 7.2用户id voucherOrder.setUserId(userId); // 7.3代金券id voucherOrder.setVoucherId(voucherId); save(voucherOrder); // 8.返回订单id return Result.ok(orderId); }}