All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitee.easyopen.util.RedisLockUtil Maven / Gradle / Ivy

package com.gitee.easyopen.util;

import java.util.Collections;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;

/**
 * redis分布式锁,详见:https://blog.csdn.net/thc1987/article/details/80355155
* 思路: *
 * 用SETNX命令,SETNX只有在key不存在时才返回成功。这意味着只有一个线程可以成功运行SETNX命令,而其他线程会失败,然后不断重试,直到它们能建立锁。
 * 然后使用脚本来创建锁,因为一个redis脚本同一时刻只能运行一次。
 * 创建锁代码:
 * 
-- KEYS[1] key,
-- ARGV[1] value,
-- ARGV[2] expireTimeMilliseconds

if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then 
    redis.call('pexpire', KEYS[1], ARGV[2]) 
    return 1 
else 
    return 0 
end
 * 
 * 最后使用脚本来解锁。
 * 解锁代码:
 * 
 * 
-- KEYS[1] key,
-- ARGV[1] value
if redis.call("get", KEYS[1]) == ARGV[1]
then
    return redis.call("del", KEYS[1])
else
    return 0
end
 * 
 * 
* * @author tanghc */ public class RedisLockUtil { private static final Long SUCCESS = 1L; /** 加锁脚本 */ private static final String SCRIPT_LOCK = "if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then redis.call('pexpire', KEYS[1], ARGV[2]) return 1 else return 0 end"; /** 解锁脚本 */ private static final String SCRIPT_UNLOCK = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; /** 加锁脚本sha1值 */ private static final String SCRIPT_LOCK_SHA1 = DigestUtils.sha1Hex(SCRIPT_LOCK); /** 解锁脚本sha1值 */ private static final String SCRIPT_UNLOCK_SHA1 = DigestUtils.sha1Hex(SCRIPT_UNLOCK); /** * 尝试获取分布式锁 * * @param redisTemplate * Redis客户端 * @param lockKey * 锁 * @param requestId * 请求标识 * @param expireTimeMilliseconds * 超期时间,多少毫秒后这把锁自动释放 * @return 返回true表示拿到锁 */ @SuppressWarnings("unchecked") public static boolean tryGetDistributedLock(@SuppressWarnings("rawtypes") final RedisTemplate redisTemplate, final String lockKey, final String requestId, final int expireTimeMilliseconds) { Object result = redisTemplate.execute(new RedisScript() { @Override public String getSha1() { return SCRIPT_LOCK_SHA1; } @Override public Class getResultType() { return Long.class; } @Override public String getScriptAsString() { return SCRIPT_LOCK; } }, // KEYS[1] Collections.singletonList(lockKey), // ARGV[1] requestId, // ARGV[2] String.valueOf(expireTimeMilliseconds) ); return SUCCESS.equals(result); } /** * 释放分布式锁 * * @param redisTemplate * Redis客户端 * @param lockKey * 锁 * @param requestId * 请求标识 * @return 返回true表示释放锁成功 */ @SuppressWarnings("unchecked") public static boolean releaseDistributedLock(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate, String lockKey, String requestId) { Object result = redisTemplate.execute(new RedisScript() { @Override public String getSha1() { return SCRIPT_UNLOCK_SHA1; } @Override public Class getResultType() { return Long.class; } @Override public String getScriptAsString() { return SCRIPT_UNLOCK; } }, Collections.singletonList(lockKey), requestId); return SUCCESS.equals(result); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy