Redis分布式锁的正确实现方式

https://blog.csdn.net/yb223731/article/details/90349502

首先,set()加入了NX参数,可以保证如果已有key存在,则函数不会调用成功,也就是只有一个客户端能持有锁,满足互斥性。其次,由于我们对锁设置了过期时间,即使锁的持有者后续发生崩溃而没有解锁,锁也会因为到了过期时间而自动解锁(即key被删除),不会发生死锁。最后,因为我们将value赋值为requestId,代表加锁的客户端请求标识,那么在客户端在解锁的时候就可以进行校验是否是同一个客户端

public class DistributedLock
{
    private static final String LOCK_SUCCESS = "OK";

    private static final String SET_IF_NOT_EXIST = "NX";

    private static final String SET_WITH_EXPIRE_TIME = "PX";

    /**
     * 尝试获取分布式锁
     * @param redisTemplate Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @param expireTime 超期时间 传入参数单位秒 如:60 即60秒
     * @return 是否获取成功
     */
    public static boolean getDistributedLock(RedisClientTemplate redisTemplate, String lockKey, String requestId,
            int expireTime)
    {
        String result = redisTemplate.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime * 1000);
        if (LOCK_SUCCESS.equals(result))
        {
            return true;
        }
        return false;
    }

    /**
     * 
     * @方法描述: 释放分布式锁
     * @创建时间: 2019年7月10日 下午5:37:28
     * @param redisTemplate
     * @param lockKey
     * @param requestId
     * @return boolean
     */
    public static boolean releaseDistributedLock(RedisClientTemplate redisTemplate, String lockKey, String requestId)
    {
        // if redis.call('get','lockKey')=='requestId' then return
        // redis.call('del','lockKey') else return 0 end
        StringBuilder sbScript = new StringBuilder();
        sbScript.append("if redis.call('get','").append(lockKey).append("')").append("=='").append(requestId)
                .append("'").append(" then ").append("    return redis.call('del','").append(lockKey).append("')")
                .append(" else ").append("    return 0").append(" end");
        return Integer.valueOf(redisTemplate.eval(sbScript.toString()).toString()) > 0;
    }
}

 

 

String requestId = UUID.randomUUID().toString();
        boolean flag = DistributedLock.getDistributedLock(redisClientTemplate, key, requestId,
                PropertiesUtil.getExpireSeconds());
        if (flag)
        {
            try
            {
                // 业务逻辑
                return true;
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                DistributedLock.releaseDistributedLock(redisClientTemplate, key, requestId);
            }
        }

 

你可能感兴趣的:(java编程,分布式系统)