• Redis与分布式-分布式锁


    接上文 Redis与分布式-集群搭建

    1.分布式锁

    在这里插入图片描述
    在这里插入图片描述
    为了解决上述问题,可以利用分布式锁来实现。
    重新复制一份redis,配置文件都是刚下载时候的不用更改,然后启动redis服务和redis客户。
    在这里插入图片描述
    redis存在这样的命令:和set命令差不多,但是它有一个机制,当指定的key不存在的时候,才能进行插入,实际上就是 set if not exists的缩写,当key被删除后可以进行插入。

    setnx key value
    
    • 1

    在这里插入图片描述

    利用这种特性,可以再不同的服务中实现分布式锁。但是若某个服务加了锁并且卡顿了,或者崩溃,那么这把锁永远无法释放了,因此可以加过期时间:set a666 EX 5 NX

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    如果学习过JUC并发编程,会发现若在超时之前那一刻进入到释放锁的阶段,获取到的值肯定还是自己,但是在即将执行删除之前,由于超时机制导致被删除并且其他任务也加锁了,那么这时候在删除,仍会导致删除其他任务加的锁
    在这里插入图片描述
    导入Redisson依赖

    <dependency>
        <groupId>org.redisson</groupId>
        <artifactId>redisson</artifactId>
        <version>3.17.0</version>
    </dependency>
    
    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.75.Final</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述
    不加锁的情况

        public static void main(String[] args) {
            for (int i = 0; i < 10; i++) {
                new Thread(() -> {
                    try(Jedis jedis = new Jedis("192.168.0.10", 6379)){
                        for (int j = 0; j < 100; j++) {   //每个客户端获取a然后增加a的值再写回去,如果不加锁那么肯定会出问题
                            int a = Integer.parseInt(jedis.get("a")) + 1;
                            jedis.set("a", a+"");
                        }
                    }
                }).start();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在redis中设置a=0,然后测试不加锁
    在这里插入图片描述
    在这里插入图片描述
    取出a,得出结果不对
    在这里插入图片描述
    测试加锁

    public static void main(String[] args) {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://192.168.0.10:6379");   //配置连接的Redis服务器,也可以指定集群
        RedissonClient client =  Redisson.create(config);   //创建RedissonClient客户端
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try(Jedis jedis = new Jedis("192.168.0.10", 6379)){
                    RLock lock = client.getLock("testLock");    //指定锁的名称,拿到锁对象
                    for (int j = 0; j < 100; j++) {
                        lock.lock();    //加锁
                        int a = Integer.parseInt(jedis.get("a")) + 1;
                        jedis.set("a", a+"");
                        lock.unlock();   //解锁
                    }
                }
                System.out.println("结束!");
            }).start();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    执行完a的值加了1000,此时写入为正常
    在这里插入图片描述

    此时若用于存放锁的redis服务挂了,那么肯定会出问题的,这个时候可以用RedLock,它的思路是在多个redis服务器上保持锁,只需要超过半数的redis服务获取到锁,那么就真的获取到锁了,这样挂掉一部分节点,也能保证正常运行。

  • 相关阅读:
    深入理解强化学习——强化学习和有监督学习
    企业级SpringBoot单体项目模板 —— 基础应用搭建
    RocketMQ实战之常用运维命令
    JS的优化技巧
    网络安全系列-三十一:基于kali系统安装CALDERA【建立在MITRE ATT&CK™之上的网络安全平台】
    Unity 3D 2022.1 AND UnityHub 3.2 Patch
    三、Zabbix — 自定义监控
    shell连接Oracle 监控表数据实时性
    JS前端实现身份证号码合法性校验(校验码校验)
    docker 部署私人 nuget 服务
  • 原文地址:https://blog.csdn.net/weixin_43917045/article/details/133466762