【实践篇】Redis最强Java客户端(三)之Redisson 7种分布式锁使用指南

文章目录

  • [0. 前言](#0. 前言)
  • [1. Redisson 7种分布式锁使用指南](#1. Redisson 7种分布式锁使用指南)
    • [1.1 简单锁:](#1.1 简单锁:)
    • [1.2 公平锁:](#1.2 公平锁:)
    • [1.3 可重入锁:](#1.3 可重入锁:)
    • [1.4 红锁:](#1.4 红锁:)
    • [1.5 读写锁:](#1.5 读写锁:)
    • [1.6 信号量:](#1.6 信号量:)
    • [1.7 闭锁:](#1.7 闭锁:)
  • [2. Spring boot 集成Redisson 验证分布式锁](#2. Spring boot 集成Redisson 验证分布式锁)
  • [3. 参考资料](#3. 参考资料)
  • [4. 源码地址](#4. 源码地址)
  • [5. Redis从入门到精通系列文章](#5. Redis从入门到精通系列文章)

0. 前言

前两章我们了解了《【实践篇】Redis最强Java客户端(一)之Redisson入门介绍》《【实践篇】Redis最强Java客户端(二)之Redisson基础概念》本章第三章主要介绍Redisson的七种分布式锁,分别是简单锁、公平锁、可重入锁、红锁、读写锁、信号量和闭锁。下面是每种锁的基本概念、使用方法以及性能和并发控制方面的考虑。

1. Redisson 7种分布式锁使用指南

1.1 简单锁:

  • 简单锁是最基本的分布式锁,通过调用Redisson的getLock()方法来获取锁,并使用lock()unlock()方法来加锁和解锁。
  • 简单锁在性能方面表现良好,可以提供良好的并发控制。
java 复制代码
RLock lock = redisson.getLock("myLock");
lock.lock();
try {
    // 执行需要加锁的业务逻辑
} finally {
    lock.unlock();
}

1.2 公平锁:

  • 公平锁是按照请求锁的顺序来获取锁的,先到先得。通过调用Redisson的getFairLock()方法来获取公平锁。
  • 性能和公平性控制:公平锁在性能方面相对较低,因为需要维护一个请求锁的队列来保证公平性。
java 复制代码
RLock fairLock = redisson.getFairLock("myFairLock");
fairLock.lock();
try {
    // 执行需要加锁的业务逻辑
} finally {
    fairLock.unlock();
}

1.3 可重入锁:

  • 可重入锁是可以被同一个线程多次获取的锁。通过调用Redisson的getReentrantLock()方法来获取可重入锁。
  • 性能和重入控制:可重入锁在性能方面表现良好,并且可以通过计数器来控制锁的重入次数。
java 复制代码
RReentrantLock reentrantLock = redisson.getReentrantLock("myReentrantLock");
reentrantLock.lock();
try {
    // 执行需要加锁的业务逻辑
} finally {
    reentrantLock.unlock();
}

1.4 红锁:

  • 红锁是在多个Redis实例上获取锁的一种机制,要求大多数Redis实例成功获取锁才算成功。通过调用Redisson的getRedLock()方法来获取红锁。
  • 性能和分布式锁控制:红锁在性能方面相对较低,因为需要在多个Redis实例之间进行同步。
java 复制代码
RLock lock1 = redisson.getLock("lock1");
RLock lock2 = redisson.getLock("lock2");
RLock lock3 = redisson.getLock("lock3");
RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
redLock.lock();
try {
    // 执行需要加锁的业务逻辑
} finally {
    redLock.unlock();
}

1.5 读写锁:

  • 读写锁是同时支持读操作和写操作的锁。通过调用Redisson的getReadWriteLock()方法来获取读写锁。
  • 读写锁在读操作方面允许并发访问,但在写操作方面只允许一个线程访问。
java 复制代码
RReadWriteLock readWriteLock = redisson.getReadWriteLock("myReadWriteLock");
RLock readLock = readWriteLock.readLock();
RLock writeLock = readWriteLock.writeLock();
readLock.lock();
try {
    // 执行需要读取的业务逻辑
} finally {
    readLock.unlock();
}

writeLock.lock();
try {
    // 执行需要写入的业务逻辑
} finally {
    writeLock.unlock();
}

1.6 信号量:

  • 信号量是一种用于控制并发访问数量的锁。通过调用Redisson的getSemaphore()方法来获取信号量。
  • 信号量可以控制同时访问的线程数量,从而控制并发访问。
java 复制代码
RSemaphore semaphore = redisson.getSemaphore("mySemaphore");
semaphore.acquire();
try {
    // 执行需要并发控制的业务逻辑
} finally {
    semaphore.release();
}

1.7 闭锁:

  • 闭锁是一种用于等待其他线程完成任务的同步工具。通过调用Redisson的getCountDownLatch()方法来获取闭锁。
  • 闭锁可以等待其他线程完成任务后再继续执行。
java 复制代码
RCountDownLatch latch = redisson.getCountDownLatch("myLatch");
latch.trySetCount(1);

// 等待其他线程完成任务
latch.await();

// 执行需要等待的业务逻辑

以上是Redisson的七种分布式锁的基本概念、使用方法以及性能和并发控制方面的考虑。这些分布式锁可以在分布式环境中提供可靠的并发控制和资源访问解决方案。

2. Spring boot 集成Redisson 验证分布式锁

  1. 添加Redisson依赖
xml 复制代码
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.15.5</version>
</dependency>
  1. 配置Redisson连接
bash 复制代码
# Redisson连接信息
spring.redis.host=127.0.0.1
spring.redis.port=6379
# 其他Redisson配置(可选)
spring.redisson.config=classpath:redisson.yaml
  1. 创建Redisson配置文件(可选)
yaml 复制代码
singleServerConfig:
  address: "redis://127.0.0.1:6379"
  1. 使用Redisson
java 复制代码
package com.example.redissondemo.controller;

import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LockController {

    @Autowired
    RedissonClient redissonClient;

    @GetMapping("/lock")
    public void testLock() throws InterruptedException {

        // 1. 可重入锁(Reentrant Lock)
        RLock reentrantLock = redissonClient.getLock("reentrantLock");
        reentrantLock.lock();
        try {
            // critical section / business logic
        } finally {
            reentrantLock.unlock();
        }

        // 2. 公平锁(Fair Lock)
        RLock fairLock = redissonClient.getFairLock("fairLock");
        fairLock.lock();
        try {
            // critical section / business logic
        } finally {
            fairLock.unlock();
        }

        // 3. 读写锁(Read-Write Lock)
        RReadWriteLock rwLock = redissonClient.getReadWriteLock("rwLock");
        
        // 写锁
        rwLock.writeLock().lock();
        try {
            // write data
        } finally {
            rwLock.writeLock().unlock();
        }
        
        // 读锁
        rwLock.readLock().lock();
        try {
            // read data
        } finally {
            rwLock.readLock().unlock();
        }

        // 4. 联锁(MultiLock)
        RLock lock1 = redissonClient.getLock("lock1");
        RLock lock2 = redissonClient.getLock("lock2");
        RLock lock3 = redissonClient.getLock("lock3");
        RLock multiLock = redissonClient.getMultiLock(lock1, lock2, lock3);
        multiLock.lock();
        try {
            // combined business operations on lock1, lock2 and lock3
        } finally {
            multiLock.unlock();
        }

        // 5. 红锁(RedLock)
        RLock redLock = redissonClient.getRedLock(lock1, lock2, lock3);
        redLock.lock();
        try {
            // combined business operations on lock1, lock2 and lock3
        } finally {
            redLock.unlock();
        }

        // 6. 自动过期锁(Auto-expiring Lock)
        RLock autoExpireLock = redissonClient.getLock("autoExpireLock");
        autoExpireLock.lock();
        try {
            // critical section / business logic
        } finally {
            autoExpireLock.forceUnlock();
        }

        // 7. 闭锁(CountDownLatch Lock)
        RCountDownLatch latch = redissonClient.getCountDownLatch("latchLock");
        latch.trySetCount(1);
        latch.await();
        
        // to release the latch
        latch.countDown();
    }
}

如果想自定义配置可以这样写,不依赖于Spring boot 注入bean 手动构造一个client 提交给Spring 容器

bash 复制代码
@java
public class RedissonConfig {

    @Value("${redisson.address}")
    private String addressUrl;

    @Value("${redisson.password}")
    private String password;

    @Bean
    public RedissonClient getRedisson(){
        Config config = new Config();
        config.useSingleServer().setAddress(addressUrl).setPassword(password);
        return Redisson.create(config);
    }
}

3. 参考资料

  1. Redisson官方网站:https://redisson.org/

  2. Redisson GitHub仓库:https://github.com/redisson/redisson

  3. redisson 参考文档 https://redisson.org/documentation.html

4. 源码地址

https://github.com/wangshuai67/icepip-springboot-action-examples
https://github.com/wangshuai67/Redis-Tutorial-2023

5. Redis从入门到精通系列文章

相关推荐
Abladol-aj1 小时前
并发和并行的基础知识
java·linux·windows
清水白石0081 小时前
从一个“支付状态不一致“的bug,看大型分布式系统的“隐藏杀机“
java·数据库·bug
Francek Chen6 小时前
【大数据技术基础 | 实验十二】Hive实验:Hive分区
大数据·数据仓库·hive·hadoop·分布式
吾日三省吾码6 小时前
JVM 性能调优
java
弗拉唐7 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi778 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
少说多做3438 小时前
Android 不同情况下使用 runOnUiThread
android·java
知兀8 小时前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
蓝黑20209 小时前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea