1. 程式人生 > 資料庫 >redis 分散式鎖的LUA實現

redis 分散式鎖的LUA實現

import org.junit.Test;
import org.junit.runner.RunWith;
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.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Collections;
import java.util.UUID;

/**
 * @author tangjianghua
 * @date 2020/11/23
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class RedisLock {

    @Autowired
    private RedisTemplate redisTemplate;

    public final String LUA_SETNX = "return redis.call('SET',KEYS[1],ARGV[1],'NX','EX',ARGV[2])";
    public final DefaultRedisScript<String> REDIS_LOCK_SCRIPT = new DefaultRedisScript<>(LUA_SETNX, String.class);


    public final String LUA_DEL = "if (redis.call('GET', KEYS[1]) == ARGV[1]) then return redis.call('DEL',KEYS[1]) else return 0 end";
    public final DefaultRedisScript<String> REDIS_UNLOCK_SCRIPT = new DefaultRedisScript<>(LUA_DEL, String.class);


    @Test
    public void test() {
        String key = "test";
        String value = UUID.randomUUID().toString();
        boolean lock = lock(key, value, 60L);
        System.out.println(lock);

        if(lock){
            boolean unLock = unLock(key, value);
            System.out.println(unLock);
        }
    }

    public boolean lock(String key,String value,long expiration){
        Object execute = redisTemplate.execute(REDIS_LOCK_SCRIPT, Collections.singletonList(key), value, String.valueOf(expiration));
        return execute!=null && execute.equals("OK");
    }

    public boolean unLock(String key,String value){
        Object execute = redisTemplate.execute(REDIS_UNLOCK_SCRIPT, Collections.singletonList(key), value);
        return execute!=null && execute.equals(1L);
    }

}