• Redis分布式锁Redisson


    分布式锁

    分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。

    分布式锁的核心是实现多进程之间互斥,而满足这一点的方式有很多,常见的有三种:

    在这里插入图片描述

    不可重入Redis分布式锁

    原理:利用setnx的互斥性;利用ex避免死锁;释放锁时判断线程标示 缺陷:不可重入、无法重试、锁超时失效

    实现分布式锁时需要实现的两个基本方法:

    • 获取锁:
      • 互斥:确保只能有一个线程获取锁

        • 添加锁,利用setnx的互斥特性
        • 添加锁过期时间,避免服务宕机引起的死锁

    在这里插入图片描述

    • 释放锁
      • 手动释放
      • 超时释放:获取锁时添加一个超时时间
    # 释放锁,删除即可
    DEL key
    
    • 1
    • 2

    分布式锁实现,满足:

    在获取锁时存入线程标示(可以用UUID表示)
    在释放锁时先获取锁中的线程标示,判断是否与当前线程标示一致
    如果一致则释放锁
    如果不一致则不释放锁

    Redisson

    https://github.com/redisson/redisson

    快速入门

    可重入的Redis分布式锁

    原理:利用hash结构,记录线程标示和重入次数;利用watchDog延续锁时间;利用信号量控制锁重试等待
    缺陷:redis宕机引起锁失效问题

    依赖

    <dependency>
        <groupId>org.redissongroupId>
        <artifactId>redissonartifactId>
        <version>3.13.6version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置Redisson客户端:

    
    import org.redisson.Redisson;
    import org.redisson.api.RedissonClient;
    import org.redisson.config.Config;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class RedisConfig {
    
        @Bean
        public RedissonClient redisClient() {
    
            Config config = new Config();
            config.useSingleServer().setAddress("redis://47.96.16.107:6379").setPassword("654321");
    
            return Redisson.create(config);
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    使用

    @Resource
    private RedissonClient redissonClient;
    
    @Test
    void testRedisson() throws InterruptedException {
        // 获取锁(可重入),指定锁的名称
        RLock lock = redissonClient.getLock("anyLock");
        // 尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位     
        boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);
        // 判断释放获取成功     
        if (isLock) {
            try {
                System.out.println("执行业务");
            } finally {
                // 释放锁
                lock.unlock();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Redisson的multiLock

    配置类

    import org.redisson.Redisson;
    import org.redisson.api.RedissonClient;
    import org.redisson.config.Config;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class RedisConfig {
    
        @Bean
        public RedissonClient redisClient1() {
    
            Config config = new Config();
            config.useSingleServer().setAddress("redis://47.96.16.107:6379").setPassword("654321");
    
            return Redisson.create(config);
        }
        
        @Bean
        public RedissonClient redisClient2() {
    
            Config config = new Config();
            config.useSingleServer().setAddress("redis://47.96.16.107:6380").setPassword("654321");
    
            return Redisson.create(config);
        }
        
        @Bean
        public RedissonClient redisClient3() {
    
            Config config = new Config();
            config.useSingleServer().setAddress("redis://47.96.16.107:6381").setPassword("654321");
    
            return Redisson.create(config);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    multiLock

    import lombok.extern.slf4j.Slf4j;
    import org.junit.jupiter.api.Test;
    import org.redisson.api.RLock;
    import org.redisson.api.RedissonClient;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import javax.annotation.Resource;
    import java.util.concurrent.TimeUnit;
    
    
    @Slf4j
    @SpringBootTest
    class SimpleLockTest {
    
    
        @Resource
        private RedissonClient redissonClient1;
    
        @Resource
        private RedissonClient redissonClient2;
    
        @Resource
        private RedissonClient redissonClient3;
    
        @Test
        void testRedisson() throws InterruptedException {
    
            RLock lock1 = redissonClient1.getLock("apple");
            RLock lock2 = redissonClient2.getLock("apple");
            RLock lock3 = redissonClient3.getLock("apple");
    
            RLock lock = redissonClient1.getMultiLock(lock1, lock2, lock3);
    
    //        // 获取锁(可重入),指定锁的名称
    //        RLock lock = redissonClient.getLock("anyLock");
            // 尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位
            boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);
            // 判断释放获取成功
            if (isLock) {
                try {
                    System.out.println("执行业务");
                } finally {
                    // 释放锁
                    lock.unlock();
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
  • 相关阅读:
    deeplab v3+ 源码详解
    音频混音算法的实现
    10-SRCNN-使用CNN实现超分辨成像
    小米、华为、iPhone、OPPO、vivo如何在手机让几张图拼成一张?
    用最少的代码打造一个Mini版的gRPC框架
    C# Winform无边框窗体实现界面拖动
    OM | 电子商务平台中的合约选择:批发合约or代理合约?
    cache2go-源码阅读
    【兔子机器人】项目资料汇总及任务流程
    LA@二次型@标准化相关原理和方法
  • 原文地址:https://blog.csdn.net/CSDN_SAVIOR/article/details/126465310