找回密码
 立即注册
首页 业界区 安全 redis实现分布式锁1

redis实现分布式锁1

晖顶蝇 2025-9-25 21:51:21
在集群下的并发问题:
1.png

业务流程:
2.png

具体实现:
ILock
点击查看代码
  1. package com.hmdp.utils;
  2. public interface ILock {
  3.     // 获取锁
  4.     boolean tryLock(long timeoutSec);
  5.     // 释放锁
  6.     void unlock();
  7. }
复制代码
SimpleRedisLock
点击查看代码
  1. package com.hmdp.utils;
  2. import org.springframework.data.redis.core.StringRedisTemplate;
  3. import java.util.concurrent.TimeUnit;
  4. public class SimpleRedisLock implements ILock {
  5.     private String name;
  6.     private StringRedisTemplate stringRedisTemplate;
  7.     private static final String KEY_PREFIX = "lock:";
  8.     public SimpleRedisLock(String name, StringRedisTemplate stringRedisTemplate) {
  9.         this.name = name;
  10.         this.stringRedisTemplate = stringRedisTemplate;
  11.     }
  12.     @Override
  13.     public boolean tryLock(long timeoutSec) {
  14.         // 获取线程的标识
  15.         long threadId = Thread.currentThread().getId();
  16.         // 获取锁
  17.         Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId + "", timeoutSec, TimeUnit.SECONDS);
  18.         return Boolean.TRUE.equals(success);
  19.     }
  20.     @Override
  21.     public void unlock() {
  22.         // 释放锁
  23.         stringRedisTemplate.delete(KEY_PREFIX + name);
  24.     }
  25. }
复制代码
VoucherOrderServiceImpl
点击查看代码
  1. package com.hmdp.service.impl;
  2. import com.hmdp.dto.Result;
  3. import com.hmdp.entity.SeckillVoucher;
  4. import com.hmdp.entity.VoucherOrder;
  5. import com.hmdp.mapper.VoucherOrderMapper;
  6. import com.hmdp.service.ISeckillVoucherService;
  7. import com.hmdp.service.IVoucherOrderService;
  8. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  9. import com.hmdp.utils.RedisIdWorker;
  10. import com.hmdp.utils.SimpleRedisLock;
  11. import com.hmdp.utils.UserHolder;
  12. import org.springframework.aop.framework.AopContext;
  13. import org.springframework.data.redis.core.StringRedisTemplate;
  14. import org.springframework.stereotype.Service;
  15. import org.springframework.transaction.annotation.Transactional;
  16. import javax.annotation.Resource;
  17. import java.time.LocalDateTime;
  18. /**
  19. * <p>
  20. *  服务实现类
  21. * </p>
  22. *
  23. * @author ztn
  24. * @since 2025-09-23
  25. */
  26. @Service
  27. public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {
  28.     @Resource
  29.     private ISeckillVoucherService seckillVoucherService;
  30.     @Resource
  31.     private RedisIdWorker redisIdWorker;
  32.     @Resource
  33.     private StringRedisTemplate stringRedisTemplate;
  34.     @Override
  35.     public Result seckillVocher(Long voucherId) {
  36.         // 1.查询优惠券
  37.         SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
  38.         // 2.判断秒杀是否开始
  39.         if(voucher.getBeginTime().isAfter(LocalDateTime.now())){
  40.             return Result.fail("秒杀尚未开始");
  41.         }
  42.         // 3.判断秒杀是否结束
  43.         if(voucher.getEndTime().isBefore(LocalDateTime.now())){
  44.             return Result.fail("秒杀已经结束");
  45.         }
  46.         // 4.判断库是否充足
  47.         if(voucher.getStock() < 1){
  48.             return Result.fail("库存不足");
  49.         }
  50.         Long userId = UserHolder.getUser().getId();
  51.         // 创建锁对象
  52.         SimpleRedisLock lock = new SimpleRedisLock("order:" + userId, stringRedisTemplate);
  53.         // 获取锁
  54.         boolean isLock = lock.tryLock(1200);
  55.         // 判断是否获取锁成功
  56.         if(!isLock){
  57.             // 获取锁失败,返回错误或重试
  58.             return Result.fail("不允许重复下单");
  59.         }
  60.         try {
  61.             // 获取代理对象(事务)
  62.             IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
  63.             return proxy.createVoucherOrder(voucherId);
  64.         }finally {
  65.             // 释放锁
  66.             lock.unlock();
  67.         }
  68.     }
  69.     @Transactional
  70.     public  Result createVoucherOrder(Long voucherId) {
  71.         // 5.一人一单
  72.         Long userId = UserHolder.getUser().getId();
  73.         // 5.1 查询订单
  74.         int count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();
  75.         // 5.2 判断是否存在
  76.         if(count > 0){
  77.             // 用户已经购买过了
  78.             return Result.fail("用户已经购买过一次了");
  79.         }
  80.         // 6.扣减库存
  81.         boolean success = seckillVoucherService.update()
  82.                 .setSql("stock = stock - 1") // set stock =stock -1
  83.                 .eq("voucher_id", voucherId)
  84. //                .eq("stock",voucher.getStock()) // where id = ? and stock = ?
  85.                 .gt("stock",0) // where id = ? and stock > 0
  86.                 .update();
  87.         if(!success){
  88.             return Result.fail("库存不足");
  89.         }
  90.         // 7.创建订单
  91.         VoucherOrder voucherOrder = new VoucherOrder();
  92.         // 7.1订单id
  93.         long orderId = redisIdWorker.nextId("order");
  94.         voucherOrder.setId(orderId);
  95.         // 7.2用户id
  96.         voucherOrder.setUserId(userId);
  97.         // 7.3代金券id
  98.         voucherOrder.setVoucherId(voucherId);
  99.         save(voucherOrder);
  100.         // 8.返回订单id
  101.         return Result.ok(orderId);
  102.     }
  103. }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册