Redisson使用(可重入锁,信号量,闭锁)

Redisson使用(可重入锁,信号量,闭锁)

在分布式系统大行其道的年代,JUC包下的单机锁,已经不能适用了。这时分布式锁应运而生。分布式锁的实现方法有很多,相信大家最最常用的,应该是结合redis的分布式锁了。如果要使用redis的分布式锁,就需要实现the Redlock algorithm。这个时候就出现了Redisson,也就是我们JAVA版本的the Redlock algorithm实现。

1、什么是Redisson?

我们来看一下,较为官方的说法。

Redisson是一个在Redis的基础上实现的Java固定内存数据网格(In-Memory Data Grid)。它既提供了一系列的分布式的Java常用对象,又提供了很多分布式服务。其中包括(BitSetSetMultimapSortedSetMapListQueueBlockingQueueDequeBlockingDequeSemaphoreLockAtomicLongCountDownLatchPublish / SubscribeBloom filterRemote serviceSpring cacheExecutor serviceLive Object serviceScheduler service)Redisson提供了使用的Redis的最简单和最便捷的方法.Redisson的宗旨是促进使用者对Redis的的关注分离(相关分离),从而让使用者能够将能量更集中地放在处理业务逻辑上。

2、SpringBoot整合Redisson(redis单机部署)

首先创建一个springboot项目,然后导入依赖,pom文件如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.redission</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>test</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.2.4.RELEASE</version>
        </dependency>

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


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

然后编写配置类RedissonConfig

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;

import java.io.IOException;

/**
 * @author xiaos
 * @version 1.0
 * @description
 * @date 2021/1/26 15:56
 */
@Configuration
public class RedissonConfig {

    @Bean(destroyMethod = "shutdown")
    RedissonClient redisson() throws IOException{
        Config config = new Config();
        //这里设置redis的地址和密码
        config.useSingleServer()
                .setAddress("redis://localhost:6379")
                .setPassword("123456");
        return Redisson.create(config);
    }
}

然后编写一个controller,测试一下简单的可重入锁是否成功

import org.redisson.api.RLock;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author xiaos
 * @version 1.0
 * @description
 * @date 2021/1/26 16:15
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private RedissonClient redisson;

    @GetMapping("/hello")
    public String hello(){
        //1、获取一把锁,只要锁名一样就获取同一把锁
        RLock rlock = redisson.getLock("lock-1");
        rlock.lock();
        try {
            System.out.println("执行业务逻辑");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rlock.unlock();
        }
        return "hello";
    }

}

3、Redisson的信号量使用(小案例)

我们假设,有一个停车场有3个停车位,当停车位满了之后,其他要停车的就只能等待。那么我们如何将它做成一个java程序呢?

首先,我们要初始化停车位。也就是要往redis里面加入一个key和value。我这里加入的key为“park”,value为“3”。表示只有3个停车位

import org.redisson.api.RLock;
import org.redisson.api.RSemaphore;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author xiaos
 * @version 1.0
 * @description
 * @date 2021/1/26 16:15
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private RedissonClient redisson;

  	//停车方法
    @GetMapping("/park")
    public String park() throws InterruptedException {
        //这里是获取信号量的值,这个信号量的name一定要与你初始化的一致
        RSemaphore park = redisson.getSemaphore("park");
        //这里会将信号量里面的值-1,如果为0则一直等待,直到信号量>0
        park.acquire();
        //tryAcquire为非阻塞式等待
        //park.tryAcquire();
        return "ok";
    }
	//开车方法
    @GetMapping("/release")
    public String release() throws InterruptedException {
        //这里是获取信号量的值,这个信号量的name一定要与你初始化的一致
        RSemaphore park = redisson.getSemaphore("park");
        //这里会将信号量里面的值+1,也就是释放信号量
        park.release();
        return "ok";
    }

}

信号量的常用场景:

限流:当你的服务最大只能满足每秒1w的并发量时,我们可以使用信号量进行限流,当访问的请求超过1w时会进行等待(阻塞式或者非阻塞式,根据业务需求)。

4、Redisson的闭锁CountDownLatch使用(小案例)

假设学校放假了,一个班级有20个同学,需要等到20个同学全部离开教室了,我们才能锁门。

import org.redisson.api.RCountDownLatch;
import org.redisson.api.RLock;
import org.redisson.api.RSemaphore;
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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author xiaos
 * @version 1.0
 * @description
 * @date 2021/1/26 16:15
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private RedissonClient redisson;
    

    //锁门
    @GetMapping("/lockdoor")
    public String lockdoor() throws InterruptedException {
        RCountDownLatch door = redisson.getCountDownLatch("door");
        //设置一个班级有20个同学
        door.trySetCount(20);
        //需要等到20个同学全部离开,才锁门
        door.await();
        return "锁门了";
    }
    //同学离开教室
    @GetMapping("/leave/{id}")
    public String leave(@PathVariable("id")Long id) throws InterruptedException {
        RCountDownLatch door = redisson.getCountDownLatch("door");
        //表示一个同学离开
        door.countDown();
        return ""+id+"号同学离开了";
    }

}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值