Redis implements distributed locks, redis
When I cleared the email, I found a previous article about the implementation of the redis distributed lock. Someone replied-I randomly scanned the article to prevent deadlocks, the idea is to use setnx to set the value to the local time, and then read the value for time comparison when the lock fails to be obtained .. Then I replied .. Multiple application servers have the problem of time synchronization ..
In fact, it is easy and convenient to set the redis expiration time when using setnx, but usually this operation is performed through the sdk in the application because the value assignment + setting expiration is not in the same atomic operation .. So many people think it is not feasible .. You can directly use the lua script, which is simple and convenient, atomic, and has good performance.
Lock: aquire_lock_with_timeout.lua
if redis.call("exists",KEYS[1]) == 0 then local lockSrc = redis.call("setex",KEYS[1],unpack(ARGV)) if lockSrc then return "1" end return "0"endreturn "-1"
Release lock: release_lock.lua
if redis.call("get",KEYS[1]) == ARGV[1] then local lockRelease = redis.call("del",KEYS[1]) if lockRelease then return "1" end return "0"endreturn "-1"
Java as an example, load two lua scripts, then simply lock and release the lock
@Bean @Qualifier("lockScript") public RedisScript<Integer> acquireLockWithTimeout() { DefaultRedisScript redisScript = new DefaultRedisScript(); redisScript.setLocation(new ClassPathResource("redis/acquire_lock_with_timeout.lua")); redisScript.setResultType(Integer.class); return redisScript; } @Bean @Qualifier("unLockScript") public RedisScript<Integer> releaseLock() { DefaultRedisScript redisScript = new DefaultRedisScript(); redisScript.setLocation(new ClassPathResource("redis/release_lock.lua")); redisScript.setResultType(Integer.class); return redisScript; }
Private Integer acquireTimeout; // time seconds for resource occupancy lock s private Integer acquireInterval; // The time limit for trying to obtain the lock MS private Integer lockTime; // try to get the lock interval MS @ Autowired private RedisTemplate redisTemplate; @ Autowired @ Qualifier ("lockScript") private RedisScript <Integer> acquireLockWithTimeout; @ Autowired @ Qualifier ("unLockScript ") private RedisScript <Integer> releaseLock; public String tryLock (String lockKey) {String lockValue = UUID. randomUUID (). toString (); Long endTime = System. currentTimeMillis () + acquireTimeout; while (System. currentTimeMillis () <endTime) {Integer lockResult = (Integer) redisTemplate.exe cute (acquireLockWithTimeout, Collections. singletonList (lockKey), lockTime, lockValue); if (lockResult. equals (1) {return lockValue;} else {try {Thread. sleep (acquireInterval);} catch (InterruptedException ex) {continue;} return ";} public boolean releaseLock (String lockKey, String lockValue) {Integer releaseResult = (Integer) redisTemplate.exe cute (releaseLock, Collections. singletonList (lockKey), lockValue); if (releaseResult. equals (1) {return true;} return false ;}
Of course, java also has a more complex and richer component redisson.