The 12th class of Guji class Redis distributed lock
Introduction to distributed locks
Within the same JVM, we often use synchronized or Lock to solve the security problem between multiple threads. However, in the distributed architecture, between JVMs, a better locking mechanism is needed to deal with the thread security problem between cross JVM processes. The solution is to use distributed locks.
Redis principle analysis
Redis distributed lock principle
Redis Distributed locking mechanism, mainly with the help of setnx and expire Two commands complete. 1. setnx When key Does not exist, will key Set to value, If there is no operation, return 0. 2. expire set up key Expiration time. Principle analysis: 3. key Create when not present and set value And expiration time. The return value is 1. The lock is successfully obtained. as key 0 is returned directly when it exists, and lock grabbing fails. When the thread holding the lock releases the lock, it is deleted manually key, Or the expiration time is up, key Automatic deletion, lock release.
set key value[Ex seconds] [PX millisecomds] [NX|XX] EX second: Set the expiration time in seconds milliseco invalid nds: Setting duration, in milliseconds key Set when not present value, Successful return OK ,Failure Return nil XX key Set when present valuem, Successful return OK ,Failure Return nil
Lua is used in Redis
EVAL: yes Lua The script is evaluated, and the command is as follows: EVAL script numkeys key [key.......] arg [arg....] 1. script : Parameter is a segment Lua.5.1 Script program. It will be run in Redis In the server context. 2. numkeys: Parameter specifies the number of key name parameters. # In the Lua script, you can use the redis.call() function to execute the Redis command ## This script does implement setting the value of the key foo to bar eval "return redis.call('set',KEYS[1],ARGV[1])" I foo bar > OK
Jedis distributed lock implementation
Lock: call the SET key PX NX command
set key value [EX seconds] [PX millseconds] [NX|NX] key Locked key value UUID.randomUUID().tostring(). Represents the client request ID for locking. nxxx nx express SET IF NOT EXIS have access to T expx PX Represents milliseconds time: Indicates the expiration time
Lock expiration problem
It is estimated that the service operation takes 10 seconds and the lock setting takes 20 seconds. For various reasons, for example, if the STW service operation has been executed for more than 20 seconds, the service will run in the unlocked state, and data disorder will occur.
Note: STW: the Stop - The- World mechanism in Java is referred to as STW, which often occurs in fullGC. At this time, all other threads of Java application are suspended (except garbage collector)
- Increase or decrease the version number in optimistic locking mode.
- Automatic delay of watch dog
Lock expiration solution: Optimistic lock: The business logic needs to be adjusted to increase the version number. Cooperate with it, so it will invade the code.
Automatic delay mechanism of Watch dog
It will not invade business code. redisson adopts this solution.
Client 1 locked key The default lifetime is only 30 seconds. If it exceeds 30 seconds, client 1 still wants to hold this lock all the time. What should I do? Once client 1 locks successfully, it will start a watch dog The watchdog, which is a thread in the background, will check every 10 seconds if client 1 still holds a lock key, Then it will continue to extend the lock key Survival time.
Redisson distributed lock
- About Redisson
Redisson is a Redis client based on Netty. It can not only operate the native Redis data structure, but also provide users with a series of common tool classes with distributed characteristics to realize distributed locking.
Redisson distributed lock
Redis distribution Lock is similar to the Lock method of JUC. RLock interface inherits the Lock interface. The code is as follows.
Storage structure of lock:
Structural Hash of lock
key: Lock name field: UUID+ threadid value: Indicates the number of reentries
Redisson distributed locking principle
**Casa** 1. Judge whether there is“ DISLOCK" 2. If not, set UUID:1 = 1 3. Set its expiration time Lock reentry 4. key And fields exist, lock reentry 5. Execute command incrby UUID:1 1 6. result: DISLOCK: {UUID: 1 2} Lock mutual exclusion 1 .Client 2 enters 7. Judge yes KEY,No fields 8. Return expiration time 9. Client 2 spin wait
Release lock
1. judge KEY Does it exist 2. If it does not exist, return nil 3. If present, use hincryby -1 Minus 1 4. After reduction m, count > 0 If the value is still greater than 0, 0 is returned 5. After subtraction, count <= 0 ,Delete key 6. use publish Broadcast lock release message
Automatic delay of Watch dog
watch dog when locking is successful, the daemon thread is started at the same time. The default validity period is 30 seconds. The lock will be extended to 30 seconds every 10 seconds
- The watch Dog will take effect only if the specified lock time is not displayed
- lockWatchdog Timeout can set the timeout time
Sectional lock
This is Mr. cedar's ideological design
You can use segmentation(Thought source) map / reduce , ConcurrentHashMap ),Space for time. In order to achieve 600 orders per second, locks can be divided into 600/ 5 = 120 In turn, each segment can be operated 5 times in 1 second, and 120 segments can be operated 600 times per second.