文章目录

  • 分布式锁
  • 不可重入Redis分布式锁
  • Redisson
  • 快速入门
  • 可重入的Redis分布式锁
  • Redisson的multiLock


分布式锁

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

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

Redisson 分布式锁 识别 哨兵和单机 redis分布式锁和redisson分布式锁_分布式锁

不可重入Redis分布式锁

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

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

  • 获取锁:
  • 互斥:确保只能有一个线程获取锁
  • 添加锁,利用setnx的互斥特性
  • 添加锁过期时间,避免服务宕机引起的死锁

Redisson 分布式锁 识别 哨兵和单机 redis分布式锁和redisson分布式锁_分布式_02

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

分布式锁实现,满足:

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

Redisson

https://github.com/redisson/redisson

快速入门

可重入的Redis分布式锁

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

依赖

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

配置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);
    }
    
}

使用

@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();
        }
    }
}

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);
    }
}

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();
            }
        }
    }