Redis实现分布式锁

首先什么是分布式锁?
在这里插入图片描述

分布式锁解决了什么问题?
例如:现在你的线程,用synchronized实现了对一个类的监控,在单机情况下确实能实现串行化执行代码,但是如果部署到集群上去,或者启动多个application呢?用一个图来理解一下吧
在这里插入图片描述
实现思路是,让一个所有JVM都能知道和看得到的锁监视器作为一个分布式的锁,这样就解决了,分布式下,synchronized等无法解决的多线程问题。

那么有哪几种方式可以实现分布式锁呢?
我所了解的三种分别是:
1、Mysql:利用Mysql本身的互斥锁机制
2、Redis的setnx+expired
3、Zookeeper:利用节点的唯一性和有序性实现互斥

三者总结如下:
在这里插入图片描述

今天我们只要使用Redis 的 setnx 命令来实现分布式锁
在这里插入图片描述
如上图我们发现我们在第一次setnx lock 返回值为1 表示成功了,第二次我再去setnx lock 返回值为
0表示失败了
在这里插入图片描述
但我们删除锁后再尝试,又成功了。

但是实际到我们的业务,可能会出现各种各样的问题,导致锁无法及时释放,怎么办呢,我们用EXPIRE
命令设置过期时来间托底,就是,你的代码没能及时删掉锁,redis也会自己帮你删掉,防止死锁。
相关命令
在这里插入图片描述
ttl 命令查看过期时间,-2表示过期了,-1表示永不过期
在这里插入图片描述
Java相关redis 代码实现

首先定义一个接口类

public interface ILock {

    /**
     * 尝试获取锁
     * @param timeoutSec 锁持有的超时时间,过期后自动释放
     * @return true代表获取锁成功; false代表获取锁失败
     */
    boolean tryLock(long timeoutSec);

    /**
     * 释放锁
     */
    void unlock();
}

获取锁代码

/**
     * 定义一个锁的要点
     * 1.锁的对象要精确,范围不能过大,否则会影响并发度,此处对应锁的key
     * 2.上锁的执行者要明确,否则解锁时会将别人定义的锁解开,此处对应锁的value
     */
    public boolean tryLock(long timeoutSec) {
        // 获取线程标示
        String threadId = ID_PREFIX + Thread.currentThread().getId();
        // 获取锁
        Boolean success = stringRedisTemplate.opsForValue()
                .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

删除锁代码

@Override
    public void unlock() {
        // 获取线程标示
        String threadId = ID_PREFIX + Thread.currentThread().getId();
        // 获取锁中的标示
        String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
        // 判断标示是否一致
        if(threadId.equals(id)) {
            // 释放锁
            stringRedisTemplate.delete(KEY_PREFIX + name);
        }
    }

相关基本代码我们实现了,但是其中存在一些问题,例如锁误删,锁的原子性问题、

下一篇见!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值