美文网首页
Redission实现分布式锁

Redission实现分布式锁

作者: 史啸天 | 来源:发表于2021-04-09 16:54 被阅读0次

命令实现

首先我们看下redis普通的set命令,如下图: redis的set命令

我们可以看到,set命令后面出了key和value之外,还可以选择EX或PX还有NX和XX,这分别代表什么意思呢,我们来看一下效果。

#ex和px代表过期时间,EX单位是秒,PX则是毫秒
>set test ceshi PX 1000
>set test ceshi EX 1
#NX表示互斥,键不存在则设置成功
>set test ceshi NX
>(nil)
#XX则是key存在则设置成功,key不存在设置失败
>set test 1111 XX
>ok
#那么我们可以组合使用,实现分布式锁的目的
>set key value EX 5 NX
>ok
#再次设置相同key时,会返回nil
>set key value EX 5 NX
>(nil)
#那么已经设置的key是否可以追加时间呢,答案是可以的
>expire key 5
>pexpire key 5

这里需要提醒一下,redis经常说的分布式锁就是上面的方式实现的,而redis还提供了一个setnx命令,可以设置key,但是无法设置超时时间,是不推荐使用的,面试的时候也会经常问到,需要大家避免踩坑。

#redis提供的setnx命令
>setnx test programmer
>(integer) 1
#如果key不存在会设置成功,并返回个1
>setnx test code
>(integer) 0

代码实现

了解了代码实现的原理,那我们来看下代码如何实现分布式锁的,话不多说上代码。

    /**
     * 获取redis锁
     * @param lockKey      redis的key,就是锁
     * @param requestId    redis的value,保证唯一性,例如订单号、手机号
     * @param expireTime   过期时间,
     * @return
     */
    public boolean getLock(String lockKey,String requestId,int expireTime) {
        // ex表示过期时间是秒,nx保证key互斥,一条set命令保证原子性,防止并发
         String result = jedis.set(lockKey, requestId, "NX", "EX", expireTime);
         if("OK".equals(result)) {
             return true;
         }
         return false;
    }

获取到锁之后,使用完成需要释放锁,当然也可以等待超时时间到期,自动释放。这其中会涉及到一个问题,就是锁超时释放,但业务逻辑还未执行完成。下一个业务进程已经获得了锁,如果直接执行del操作,会造成释放掉了别人的锁。那么我们就需要考虑使用lua脚本,来保证释放锁的并发。

    /**
     * 使用lua脚本释放锁
     * @param lockKey    redis的key
     * @param requestId  redis的value
     * @return
     */
    public static boolean releaseLock(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 (result.equals(1L)) {
            return true;
        }
        return false;
    }

问题

redis在单机的情况下是无法保证高可用的,在生产环境中我们一般会搭建redis的集群,而redis是AP模型,那么就会存在主从数据不同步,导致redis锁重复获得的问题。
当然正常情况下,在不需要保证业务数据强一致性时,就可以使用redis的分布式锁;如果需要保证强一致性,则考虑使用其它方式,比如zookeeper等。

看门狗(Redission分布式锁)

“看门狗”基于NIO的Netty框架实现的分布式锁,多在生产环境中使用,接下来看代码。
1、引入jar包

<dependency> 
    <groupId>org.redisson</groupId> 
    <artifactId>redisson</artifactId> 
    <version>2.7.0</version> 
</dependency>

2、配置Redisson

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonManager {
    
    @Bean
    public RedissonClient redisson(){
        Config config = new Config();
        ClusterServersConfig clusterServersConfig = config.useClusterServers()
                .setScanInterval(2000) // 集群状态扫描,时间是毫秒
                .addNodeAddress("redis://127.0.0.1:6379")
                .addNodeAddress("redis://127.0.0.1:6380")
                .addNodeAddress("redis://127.0.0.1:6381")
                .addNodeAddress("redis://127.0.0.1:6382")
                .addNodeAddress("redis://127.0.0.1:6383")
                .addNodeAddress("redis://127.0.0.1:6384");
        return Redisson.create(config);
    }
}

3、使用

public void test(){
    RLock key = redissonClient.getLock("key");
    key.lock();
    // 业务代码
    key.unlock();
}

总结

以上便是使用redis实现分布式锁的过程,基本上可以满足大部分业务需求,也希望大家了解redis分布式锁的优缺点。
最后,Redisson还有很多玩法,目前是一个比较成熟的redis分布式锁框架,奉上git连接,供大家继续学习。
https://github.com/redisson/redisson/

相关文章

  • 大佬浅谈分布式锁

    redis 实现 redis 分布锁一、redis 实现分布式锁(可重入锁)redission 实现分布式锁1、对...

  • SpringBoot集成Redission + JedisPoo

    前言:因为打算用redis来实现分布式锁的功能,打算采用redis的分布式锁框架redission,但是还要用到r...

  • 2-(1)、SpringBoot整合redisson实现分布式锁

    1.springboot整合redission实现分布式锁(基本使用) 1.1.简介   Redisson是架设在...

  • 分布式锁解决方案

    redis 分布式锁解决方案 还有可以使用 redission分布式锁 参考:https://www.cnblog...

  • Redission实现分布式锁

    一.设计分布式锁的注意事项 1. 互斥 在同一时刻,只有一个线程可以获得锁,这是最基本也是最重要的一点。 2. 防...

  • Redission实现分布式锁

    命令实现 首先我们看下redis普通的set命令,如下图: 我们可以看到,set命令后面出了key和value之外...

  • 常见问题对应的文章

    redis分布式锁实现方案 单点问题Redission redLock set nx原语要加超时时间,避免客户端d...

  • 实操Redission

    实操Redission 分布式对象(一)实操Redission 分布式Map集合(二)实操Redission 分布...

  • Redission实现分布式锁(二)

    Redission是通过lua脚本来访问Redis来确保业务逻辑执行的原子性的。以下就是Redission中lua...

  • Redission分布式锁

    1,基本使用示例 使用Redission对业务的核心处理方法进行加锁处理; (1),引入依赖 (2),创建配置类 ...

网友评论

      本文标题:Redission实现分布式锁

      本文链接:https://www.haomeiwen.com/subject/sanikltx.html