RedisLock.java 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. package edu.travel.cache.config;
  2. import org.springframework.data.redis.core.StringRedisTemplate;
  3. import org.springframework.data.redis.core.script.DefaultRedisScript;
  4. import org.springframework.data.redis.core.script.RedisScript;
  5. import org.springframework.stereotype.Component;
  6. import java.util.Collections;
  7. import java.util.UUID;
  8. import java.util.concurrent.TimeUnit;
  9. @Component
  10. public class RedisLock {
  11. // 锁键的前缀,可根据业务自定义
  12. private static final String LOCK_PREFIX = "lock:";
  13. private final StringRedisTemplate redisTemplate;
  14. public RedisLock(StringRedisTemplate redisTemplate) {
  15. this.redisTemplate = redisTemplate;
  16. }
  17. /**
  18. * 获取分布式锁(使用SETNX和过期时间,保证原子性)
  19. *
  20. * @param lockKey 锁的键
  21. * @param expire 锁的过期时间(秒)
  22. * @return 锁的唯一标识(用于释放锁)
  23. */
  24. public String acquireLock(String lockKey, long expire) {
  25. String lockValue = UUID.randomUUID().toString();
  26. String key = LOCK_PREFIX + lockKey;
  27. // 使用SET命令:SET key value NX EX expire
  28. Boolean success = redisTemplate.opsForValue()
  29. .setIfAbsent(key, lockValue, expire, TimeUnit.SECONDS);
  30. return Boolean.TRUE.equals(success) ? lockValue : null;
  31. }
  32. /**
  33. * 释放分布式锁(使用Lua脚本保证原子性)
  34. *
  35. * @param lockKey 锁的键
  36. * @param lockValue 锁的唯一标识
  37. * @return 是否释放成功
  38. */
  39. public boolean releaseLock(String lockKey, String lockValue) {
  40. if (lockValue == null) return false;
  41. String key = LOCK_PREFIX + lockKey;
  42. String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
  43. "return redis.call('del', KEYS[1]) " +
  44. "else return 0 end";
  45. RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
  46. Long result = redisTemplate.execute(redisScript, Collections.singletonList(key), lockValue);
  47. return result != null && result == 1;
  48. }
  49. }