package com.ruoyi.im.util; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; @Component public class RedisDistributedLock { private final RedisTemplate redisTemplate; private static final String LOCK_PREFIX = "insurance:lock:"; public RedisDistributedLock(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } /** * 尝试获取锁 * @param lockKey 锁的key * @param expireSeconds 锁过期时间(秒) * @param waitSeconds 等待时间(秒) * @return 是否获取成功 */ public boolean tryLock(String lockKey, long expireSeconds, long waitSeconds) { String key = LOCK_PREFIX + lockKey; long endTime = System.currentTimeMillis() + waitSeconds * 1000; while (System.currentTimeMillis() < endTime) { Boolean success = redisTemplate.opsForValue().setIfAbsent(key, "locked", expireSeconds, TimeUnit.SECONDS); if (Boolean.TRUE.equals(success)) { return true; } try { // 短暂休眠后重试 Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } } return false; } /** * 获取锁(使用默认参数) */ public boolean tryLock(String lockKey) { return tryLock(lockKey, 30L, 10L); } /** * 释放锁 * @param lockKey 锁的key */ public void releaseLock(String lockKey) { String key = LOCK_PREFIX + lockKey; redisTemplate.delete(key); } /** * 生成锁的key(基于用户ID和产品ID) */ public String generateLockKey(String account, Integer productId) { // 将 %d 改为 %s 来格式化字符串 return String.format("purchase:%s:%d", account, productId); } /** * 生成基于用户ID的锁key */ public String generateUserLockKey(String account) { // 同样修正这里 return String.format("purchase:%s", account); } }