1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- package edu.travel.cache.config;
- import org.springframework.data.redis.core.StringRedisTemplate;
- import org.springframework.data.redis.core.script.DefaultRedisScript;
- import org.springframework.data.redis.core.script.RedisScript;
- import org.springframework.stereotype.Component;
- import java.util.Collections;
- import java.util.UUID;
- import java.util.concurrent.TimeUnit;
- @Component
- public class RedisLock {
- // 锁键的前缀,可根据业务自定义
- private static final String LOCK_PREFIX = "lock:";
- private final StringRedisTemplate redisTemplate;
- public RedisLock(StringRedisTemplate redisTemplate) {
- this.redisTemplate = redisTemplate;
- }
- /**
- * 获取分布式锁(使用SETNX和过期时间,保证原子性)
- *
- * @param lockKey 锁的键
- * @param expire 锁的过期时间(秒)
- * @return 锁的唯一标识(用于释放锁)
- */
- public String acquireLock(String lockKey, long expire) {
- String lockValue = UUID.randomUUID().toString();
- String key = LOCK_PREFIX + lockKey;
- // 使用SET命令:SET key value NX EX expire
- Boolean success = redisTemplate.opsForValue()
- .setIfAbsent(key, lockValue, expire, TimeUnit.SECONDS);
- return Boolean.TRUE.equals(success) ? lockValue : null;
- }
- /**
- * 释放分布式锁(使用Lua脚本保证原子性)
- *
- * @param lockKey 锁的键
- * @param lockValue 锁的唯一标识
- * @return 是否释放成功
- */
- public boolean releaseLock(String lockKey, String lockValue) {
- if (lockValue == null) return false;
- String key = LOCK_PREFIX + lockKey;
- String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
- "return redis.call('del', KEYS[1]) " +
- "else return 0 end";
- RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
- Long result = redisTemplate.execute(redisScript, Collections.singletonList(key), lockValue);
- return result != null && result == 1;
- }
- }
|