In the last article, we looked at redis’s implementation of distributed locks and the problems it encountered, which can lead to a lot of code and bugs if you’re not careful. In fact, these problems are solved by Redisson, so today we will discuss Redisson to implement distributed locking
Let’s start with a code example:
public class RedissonLock { public static void main(String[] args) { Config config = new Config(); // Single-machine mode config.usesingleserver ().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); RLock rLock = redissonClient.getLock("key"); Try {// Timeout to obtain the lock (100 ms timeout,10 ms lock time) rlock. tryLock(100,10, timeunit.seconds); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { rLock.unlock(); redissonClient.shutdown(); }}}Copy the code
Compared to Redis to implement distributed locks to consider many scenarios, this way of writing code is much cleaner. The core code is really just three lines, if we follow through we will see the source code below
return this.commandExecutor.evalWriteAsync(this.getName(), LongCodec.INSTANCE, command, "if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]);" , Collections.singletonList(this.getName()), new Object[]{this.internalLockLeaseTime, this.getLockName(threadId)});Copy the code
We can still see from it, its implementation idea is still the same idea, but Redisson uses lua script to implement us, Lua script is atomic, operation is more rigorous than we use code implementation, the most important Redisson is widely used, is verified, there is no bug.
As we mentioned earlier, what is the appropriate timeout setting for this lock? What if the time is up and the business code hasn’t finished executing? The way Redisson does it is, the thread that acquires the lock starts a background thread that monitors the thread, rotates every once in a while to see if the thread has finished executing, and if it’s not that long, extend the timeout by a third of a second, if you don’t set the timeout then Redisson defaults to 30 seconds, Then the training in rotation time interval is 10 seconds, RedissonLock. Enclosing scheduleExpirationRenewal (threadId); It is a timed task started by a background thread