1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;
public class RedisDistributedLock { private JedisPool jedisPool; private String lockKey; private String lockValue; private int expireTime; private Thread renewalThread; private volatile boolean isRunning = true; private static final String LOCK_SCRIPT = "if redis.call('set', KEYS[1], ARGV[1], 'NX', 'EX', ARGV[2]) then " + " return 1 " + "else " + " return 0 " + "end"; private static final String UNLOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then " + " return redis.call('del', KEYS[1]) " + "else " + " return 0 " + "end"; private static final String RENEWAL_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then " + " return redis.call('expire', KEYS[1], ARGV[2]) " + "else " + " return 0 " + "end"; public RedisDistributedLock(JedisPool jedisPool, String lockKey, int expireTime) { this.jedisPool = jedisPool; this.lockKey = lockKey; this.expireTime = expireTime; }
public boolean tryLock(long timeout) throws InterruptedException { lockValue = UUID.randomUUID().toString(); long start = System.currentTimeMillis(); while (System.currentTimeMillis() - start < timeout) { try (Jedis jedis = jedisPool.getResource()) { Long result = (Long) jedis.eval(LOCK_SCRIPT, Collections.singletonList(lockKey), Arrays.asList(lockValue, String.valueOf(expireTime)) ); if (result == 1) { startWatchdog(); return true; } } Thread.sleep(10); } return false; }
private void startWatchdog() { renewalThread = new Thread(() -> { while (isRunning) { try { Thread.sleep(expireTime * 1000 / 3); try (Jedis jedis = jedisPool.getResource()) { Long result = (Long) jedis.eval(RENEWAL_SCRIPT, Collections.singletonList(lockKey), Arrays.asList(lockValue, String.valueOf(expireTime)) ); if (result == 0) { System.out.println("续期失败,停止看门狗"); break; } } } catch (Exception e) { e.printStackTrace(); break; } } }); renewalThread.setDaemon(true); renewalThread.start(); }
public void unlock() { isRunning = false; if (renewalThread != null) { renewalThread.interrupt(); } try (Jedis jedis = jedisPool.getResource()) { jedis.eval(UNLOCK_SCRIPT, Collections.singletonList(lockKey), Collections.singletonList(lockValue) ); } } }
|