spring boot implement distributed lock LUA script based on the redis [it is] based on a single point at redis
.Spring boot 1.5.X achieve a distributed lock lua script based on the redis
1.pom.xml
<!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2.RedisLock tools (Spring injection)
Import org.springframework.beans.factory.annotation.Autowired; Import org.springframework.data.redis.core.RedisTemplate; Import org.springframework.data.redis.core.script.DefaultRedisScript; Import org.springframework.data.redis. core.script.RedisScript; Import org.springframework.data.redis.serializer.StringRedisSerializer; Import org.springframework.stereotype.Component; Import java.util.Collections; / ** * the Spring the Boot 1.5.X * redis use of lua script based on single-point implementation of distributed lock * * Lua script as an atomic operation, and to ensure the lock timeout setting atomic operations * @author SXD * @date 2019/5/27 10:52 * / @Component public class RedisLock { @Autowired RedisTemplate redisTemplate; Private static Final Long 1L = SUCCESS ; / ** * Get lock * * @param lockKey Redis of Key * @param value is required value redis random string, preventing the release of other requests lock * @param expiration time of expireTime redis key to prevent a deadlock that causes other requests can not perform normal operations * @return * / public boolean lock (lockKey String, String value, int expireTime) { String Script= "if redis.call('setNx',KEYS[1],ARGV[1]) then " + " if redis.call('get',KEYS[1])==ARGV[1] then " + " return redis.call('expire',KEYS[1],ARGV[2]) " + " else " + " return 0 " + " end " + "end"; RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class); //对非string类型的序列化 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); Result Object=redisTemplate.execute (redisScript, Collections.singletonList (lockKey), value, String.valueOf (expireTime)); return SUCCESS.equals (Result); } / ** * lock release * * @param lockKey Redis of Key * @param value redis only the value of the same ratio value, to determine that the present request is added to the normal release latch * @return * / public Boolean UNLOCK (lockKey String, String value) { String Script = "IF redis.call ( 'GET', KEYS [. 1]) == ARGV [. 1] redis.call the then return ( 'del', KEYS [. 1]) End the else return 0 " ; redisScript <String> = redisScript new new DefaultRedisScript<>(script, String.class); try { Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value); if (SUCCESS.equals(result)) { return true; } } catch (Exception e) { e.printStackTrace(); } return false; } }
3.controller use
/ ** * Use the Distributed Lock logic * 1. Prepare the value expireTime Key * value is required random string * expireTime lock expiration date is based on a measure of business decisions * * 2. Get lock * successful acquisition, the implementation of business execution complete, release the lock * failure to obtain, retry acquisition, pay attention to the time interval to acquire the lock until the acquisition is successful, the implementation of the business, and finally release the lock * * Note: * for redis locked business, try to use in a short time-consuming business on. * * / @RequestMapping ( "/ Test" ) public void Test () { Boolean In Flag = to false ; // identifier to acquire the lock is normal String UUID = UUID.randomUUID () toString ();. // Redis value is a string of random number = Lock.lock In Flag ( "mykey1", UUID,. 5 ); IF (In Flag) { Business (UUID); } the else { // If the lock is not acquired by the normal acquire a retry until successful lock the while (! In Flag) { the try { // retry interval to reduce the number of interactions with redis the Thread.sleep (3000 ); System.out.println ( "retry" ); In Flag = Lock.lock ( "mykey1", UUID,. 5 ); IF (In Flag) { Business (UUID); } the else { Continue ; } } the catch (InterruptedException E) { e.printStackTrace (); } } } } public void Business (UUID String) { the try { System.out.println ( "lock successful implementation of business" ); the Thread.sleep ( 10000 ); } the catch (InterruptedException E) { e.printStackTrace (); } the finally { // service execution is completed normally releasing the lock lock.unlock ( "mykey1",uuid); } }
Two .spring boot 2.x implementation of distributed lock LUA script based on the redis
1.