Redis-实现分布式锁

为什么要使用分布式锁

大多数业务服务中,都是以集群的形式部署。高并发场景下对服务共享变量进行量的操作,很容易出现并发问题。 因此需要一个分布式锁来对共享变量进行控制。

Redis 实现分布式锁思路

为什么使用Redis实现?

Redis 内部指令是单线程执行,可以利用其原子性实现锁的目的。

实现思路

最简单的思路: 获取锁,执行业务,删除锁

if   setnx(k,v) 
   do sth
else 
  do noth
finally
   del  k
问题: 锁的释放需要外部业务程序管理,若出现异常,会造成死锁

优化思路2: 获取锁,设置有效期(两个命令合二为一)

//在最初的版本中,setnx 和 expire是两个指令,因此不具有原子性.
//redis高版本增强了set的功能,可以通过set实现这两个指令的功能.

if  ( set(key,v,EX,seconds,NX) != ok)
  return
else{
   do sth 
   del key 
}
问题: 锁的释放,如果主动释放需要控制 :解铃还须系铃人

代码实现

//加锁
/**
     * 尝试获取分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 当前线程的唯一标识
     * @param expireTime 超期时间
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, long expireTime) {

        String result = jedis.set(lockKey, requestId, NX, EX, expireTime);

        if ("ok".equals(result)) {
            return true;
        }
        return false;

    }

/**
     * 释放分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 线程标识
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {

        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

        if (1.equals(result)) {
            return true;
        }
        return false;

    }
这个解锁方案相对来锁保险一点,但是如果超时了 业务逻辑还没执行完,还是会出现并发问题。
,也可以考虑使用重入锁进行解锁;

解锁方案其实可以和业务逻辑绑定到一起,这样可以直接del,避免多个客户端解锁。
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容