1 the local lock

A JDK Lock, such as Synchronize or Lock, locks only the current process and applies only to single architecture services. In distributed multi-service instance scenarios, distributed locks must be used.

2 Distributed Lock

2.1 Principle of distributed lock

Toilet squatting theory

Can go to a place “occupy pit” at the same time:

  • Capture, execute logic
  • Otherwise, wait until the lock is released

You can spin by spinning

Chancy can go to Redis, DB, anywhere that all services can access.

2.2 Distributed Lock Evolution

A phase

/ / for distributed lock to redis of pit Boolean lock = redisTemplate. OpsForValue () setIfAbsent (" lock ", "111"); If (lock) {// Lock succeeded... Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); redisTemplate . delete( key: "lock"); //fHßti return dataF romDb; } else {// Lock failed, try again. Synchronized () / / dormancy try again 100 ms / / spin return getCatalogJsonFromDbwithRedisLock (); } Duplicate codeCopy the code

Problem scenario

  • Setnx takes the hole, but the business code is abnormal or the program is down in the execution process, that is, failed to execute the delete lock logic, resulting in a deadlock

Solution: Set the lock to expire automatically, even if it is not deleted, it will be deleted automatically.

Phase two

/ / 1. Distributed lock, to redis pit of Boolean lock. = redisTemplate opsForValue () setIfAbsent (" lock ", "110") if (lock) {/ / locking success... Redistemplate. expire("lock", timeout: 30, timeunit.seconds); redistemplate. expire("lock", timeout: 30, timeunit.seconds); Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); Redistemplate. delete(key; "lock"); return dataFromDb; } else {// lock failed... Try again. Synchronized () // sleep 100ms retry // spin way return getCatalogJsonF romDbWithRedisLock(); } Duplicate codeCopy the code

Problem scenario

  • Setnx is set, and is about to set the expiration time

Solution: Setting expiration times and placeholders must be atomic operations. Redis supports the setNxEx command

Stage three

/ / 1. Distributed lock of pit Boolean lock. = redisTemplate opsForValue () setIfAbsent (" lock ", "110", 300, TimeUnit. SECONDS); Expire ("lock", з0, timeunit.seconds); expire.expire.expire ("lock", з0, timeunit.seconds); Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); Redistemplate. delete(key: "lock") return dataFromDb; The else {/ / lock fails, try again try again / / dormancy 100 ms / / spin return getCatalogJsonFromDbithRedislock ()} copy codeCopy the code

Phase four

Have got lockValue, have UUID, but expired now! Someone else took the lock and set it to a new value. Lock deletion is not an atomic operation.

Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); String lockValue = redisTemplate.opsForValue().get("lock"); If (uuid. Equals (lockValue)) {// Delete my own lock redistemplate. delete("lock"); } Duplicate codeCopy the code

Problem scenario

  • If you are about to delete the lock, the lock has expired and someone else has successfully set the new value. Then you’re deleting someone else’s lock.
  • The solution

Deleting locks must be atomic. Use the Redis +Lua script.

Stage 5

  • Make sure locking/unlocking is atomic

    String script = “if redis.call(‘get’, KEYS[1]) == ARGV[1] then return redis.call(‘del’, KEYS[1]) else return 0 end”; Copy the code

Ensure atomicity of lock [space + expiration time] and lock [judgment + delete]. The harder thing is the automatic renewal of the lock.

conclusion

In fact, more troublesome things, and the automatic renewal of the lock. So whether it is a large factory or a small or medium-sized company, we are directly selected to solve these problems Redisson! Don’t reinvent the wheel, but also know what problems the framework solves, so that we can quickly troubleshoot and locate any problems we encounter. In the next post, we’ll start with Redisson’s explanation of how he did it

By JavaEdge at the nuggets link: juejin.cn/post/692227… The copyright belongs to the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.