springboot2.x使用lettuce连接的redis使用redis锁

RedisLockUtils.java

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

/**
 * redis锁
 *
 * @author zhy
 */
@Slf4j
@Component
public class RedisLockUtils {
    @Resource
    private RedisTemplate redisTemplate;

    public static final String UNLOCK_LUA;

    /**
     * 释放锁脚本,原子操作
     */
    static {
        StringBuilder sb = new StringBuilder();
        sb.append("if redis.call(\"get\",KEYS[1]) == ARGV[1] ");
        sb.append("then ");
        sb.append("    return redis.call(\"del\",KEYS[1]) ");
        sb.append("else ");
        sb.append("    return 0 ");
        sb.append("end ");
        UNLOCK_LUA = sb.toString();
    }


    /**
     * 获取分布式锁
     *
     * @param lockKey   key
     * @param requestId 唯一id
     * @param expire    时间值
     * @param timeUnit  时间单位
     * @return true:加锁成功,false:已有人获取锁
     */
    public boolean tryLock(String lockKey, String requestId, long expire, TimeUnit timeUnit) {
        try {
            RedisCallback callback = (connection) -> connection.set(lockKey.getBytes(Charset.forName("UTF-8")), requestId.getBytes(Charset.forName("UTF-8")), Expiration.seconds(timeUnit.toSeconds(expire)), RedisStringCommands.SetOption.SET_IF_ABSENT);
            return (Boolean) redisTemplate.execute(callback);
        } catch (Exception e) {
            log.error("redis lock error.", e);
        }
        return false;
    }

    /**
     * 释放锁
     *
     * @param lockKey   key
     * @param requestId 唯一id
     * @return true:释放成功
     */
    public boolean releaseLock(String lockKey, String requestId) {
        RedisCallback callback = (connection) -> connection.eval(UNLOCK_LUA.getBytes(), ReturnType.BOOLEAN, 1, lockKey.getBytes(Charset.forName("UTF-8")), requestId.getBytes(Charset.forName("UTF-8")));
        return (Boolean) redisTemplate.execute(callback);
    }

    /**
     * 获取Redis锁的value值
     *
     * @param lockKey key
     * @return value
     */
    public String get(String lockKey) {
        try {
            RedisCallback callback = (connection) -> new String(connection.get(lockKey.getBytes()), Charset.forName("UTF-8"));
            return (String) redisTemplate.execute(callback);
        } catch (Exception e) {
            log.error("获取redis锁发生异常", e);
        }
        return null;
    }

}

测试Test

import org.junit.runner.RunWith;
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @author zhy
 * @date 2020/2/15 15:07
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class RedisTest {

    @Resource
    private RedisLockUtils redisLockUtils;

    @Test
    public void testLock() {
        String redisKey = "zhyLock";
        String requestId = "123456";
        boolean result = redisLockUtils.tryLock(redisKey, requestId, 60, TimeUnit.SECONDS);
        System.out.println("lock:" + result);
        System.out.println("release lock:" + redisLockUtils.releaseLock(redisKey, requestId));
    }
}

 

你可能感兴趣的:(java后台)