Redis分布式锁实现

一 前言

1.在多进程服务的情况下,无法通过共享锁或者synchronized关键字来实现对共享资源的访问,所以需要引入分布式锁,解决多个服务同步访问共享资源的问题。

 

二 分布式锁要解决两个问题:

(1) 线程在获取锁时,具有对资源的独占权利,并且设置超时时间,以免自身线程崩溃或占用过长,导致其他线程无法获取资源的问题

(2) 线程需要在获取锁后,对资源进行独占,进行业务处理后,未达到超时时间时,需要对锁资源及时释放。但是要注意,如果占锁线程执行时间过长,导致锁超时时间用完后,需要判断是否仍是自己获取的锁,以免释放掉别人的锁,

可以通过设置 redis key的value(UUID)来为唯一标识,占锁线程判断是否为其设置的value,进而决定是否为自身锁资源。

三 代码实现

package com.wacai.stanlee.capm.util;

import redis.clients.jedis.JedisCluster;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

public class RedisLockUtil {
    private static final String LOCK_SUCCESS = "OK";
    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 使用lua对获取当前锁,并设置过期时间
     * @param jedisCluster
     * @param lock  redis key
     * @param value 可设置java的UUID作为redis key的值
     * @param expireTime 单位为秒,默认20s
     * @return
     */
    public static boolean tryGetDistributedLock(JedisCluster jedisCluster, String lock, String value, int expireTime) {
        //串行、原子操作,保证设置lock,设置过期时间
        List<String> paras = new ArrayList<>();
        String luaOfTryLock =  "return redis.call('set',KEYS[1],ARGV[1],'NX','EX',ARGV[2])";
        paras.add(value);
        if(0 != expireTime){
            paras.add(String.valueOf(expireTime));
        }else{
            paras.add("20");
        }
        Object result = jedisCluster.eval(luaOfTryLock, Collections.singletonList(lock), paras);
        return null != result && LOCK_SUCCESS.equalsIgnoreCase(result.toString()) ;
    }

    /**
     * 在删除锁时,防止A线程把B线程的锁释放
     * 如果redis的value与所属线程加锁时的值一样,则进行锁资源释放,否则不进行释放
     * @param jedisCluster
     * @param lockKey
     * @param currentValues
     * @return
     */
    public static boolean realseLock(JedisCluster jedisCluster, String lockKey, String currentValues) {
        String luaOfReleaseLock = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return -1 end";
        Object result = jedisCluster.eval(luaOfReleaseLock, Collections.singletonList(lockKey), Collections.singletonList(currentValues));
        return  null != result && RELEASE_SUCCESS == Integer.parseInt(result.toString());
    }



}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值