RedisLockUtil.java 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package com.fdkankan.redis.util;
  2. import cn.hutool.core.util.StrUtil;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.data.redis.core.RedisTemplate;
  6. import org.springframework.data.redis.core.script.DefaultRedisScript;
  7. import org.springframework.stereotype.Component;
  8. import java.util.Arrays;
  9. import java.util.Objects;
  10. import java.util.concurrent.TimeUnit;
  11. @Component
  12. @Slf4j
  13. public class RedisLockUtil {
  14. @Autowired
  15. private RedisTemplate redisTemplate;
  16. private static final String UNLOCK_LUA =
  17. "if redis.call('get',KEYS[1]) == ARGV[1] then\n" +
  18. " return redis.call('del',KEYS[1])\n" +
  19. "else\n" +
  20. " return 0\n" +
  21. "end";
  22. /**
  23. * 加锁,自旋重试三次
  24. *
  25. * @param lockKey 锁key
  26. * @param expireTime 锁过期时间 单位 毫秒
  27. * @return
  28. */
  29. public boolean lock(String lockKey, int expireTime) {
  30. boolean locked = false;
  31. int tryCount = 3;
  32. String threadId = String.valueOf(Thread.currentThread().getId());
  33. while (!locked && tryCount > 0) {
  34. locked = redisTemplate.opsForValue().setIfAbsent(lockKey, threadId, expireTime, TimeUnit.SECONDS);
  35. tryCount--;
  36. try {
  37. Thread.sleep(300);
  38. } catch (InterruptedException e) {
  39. log.error("线程被中断[线程id:" + threadId + "]", e);
  40. }
  41. }
  42. return locked;
  43. }
  44. /**
  45. * 非原子解锁,可能解别人锁,不安全
  46. *
  47. * @return
  48. */
  49. public boolean unlock(String lockKey) {
  50. String threadId = String.valueOf(Thread.currentThread().getId());
  51. if (StrUtil.isEmpty(lockKey) || Objects.isNull(threadId))
  52. return false;
  53. boolean releaseLock = false;
  54. Long val = (Long) redisTemplate.opsForValue().get(lockKey);
  55. if (threadId.equals(val)) {
  56. releaseLock = redisTemplate.delete(lockKey);
  57. }
  58. return releaseLock;
  59. }
  60. /**
  61. * 使用lua脚本解锁,不会解除别人锁
  62. *
  63. * @param
  64. * @return
  65. */
  66. public boolean unlockLua(String lockKey) {
  67. String threadId = String.valueOf(Thread.currentThread().getId());
  68. if (StrUtil.isEmpty(lockKey) || Objects.isNull(threadId))
  69. return false;
  70. DefaultRedisScript<Long> redisScript = new DefaultRedisScript();
  71. // redisScript.setLocation(new ClassPathResource("unlock.lua"));
  72. redisScript.setScriptText(UNLOCK_LUA);
  73. redisScript.setResultType(Long.class);
  74. Object result = redisTemplate.execute(redisScript, Arrays.asList(lockKey), threadId);
  75. return result.equals(Long.valueOf(1));
  76. }
  77. }