spring boot 实现Redisson分布式锁

分布式锁,就是控制分布式系统中不同进程共同访问同一共享资源的一种锁的实现。
1、引入依赖


            org.redisson
            redisson-spring-boot-starter
            3.15.5
        

2、配置文件

spring:
	data:
		redis:
	      database: 1
	      host: localhost
	      port: 6379
	      password: *********

3、配置类

package com.example.springboot3test.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author DeyouKong
 * @description TODO
 * @date 2023/3/23 23:34
 */

@Configuration
public class RedissonConfig {
    @Value(value = "${spring.data.redis.host}")
    private String host;
    @Value(value = "${spring.data.redis.port}")
    private int port;
    @Value(value = "${spring.data.redis.database}")
    private int database;
    @Value(value = "${spring.data.redis.password}")
    private String password;


    /**
     * 单Redis节点模式配置方法
     * 其他配置參數,看:
     * 
     * 单Redis节点模式配置方法
     * 
     *
     * @return {@link RedissonClient}
     */
    @Bean(destroyMethod = "shutdown")
    RedissonClient redisson() {
        Config config = new Config();
        //Redis多节点
        // config.useClusterServers()
        //     .addNodeAddress("redis://127.0.0.1:6379", "redis://127.0.0.1:7001");


        //Redis单节点
        SingleServerConfig singleServerConfig = config.useSingleServer();
        //可以用"rediss://"来启用SSL连接
        String address = "redis://" + host + ":" + port;
        singleServerConfig.setAddress(address);
        //设置 数据库编号
        singleServerConfig.setDatabase(database);
        singleServerConfig.setPassword(password);
        //连接池大小:默认值:64
        // singleServerConfig.setConnectionPoolSize()
        return Redisson.create(config);
    }


}

4、测试代码

package com.example.springboot3test.controller;

import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/redission")
public class RedissionController {
    @Resource
    private RedissonClient redissonClient;

    private final static String LOCK="I_AM_LOCK";

    @GetMapping("/list")
    public String getString(){
        // 1、获取一把锁,只要锁的名字一样,既是同一把锁
        RLock lock = redissonClient.getLock(LOCK);
        // 2、加锁
        //lock.lock(5, TimeUnit.SECONDS); // 阻塞式等待

        if(lock.isLocked()){
            //如果存在锁,则返回失败
            return "fail";
        }

        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName()+":\t 获得锁");
            Thread.sleep(20000);
        } catch (Exception e) {
            e.printStackTrace();
            return "占用所";
        }finally {
            // 3、解锁
            lock.unlock();
            System.out.println(Thread.currentThread().getName()+":\t 释放锁锁");
        }
        return "OK";
    }
}

5、理解
一、时间设置
默认 lock() 小结
lock.lock ();
(1)默认指定锁时间为30s(看门狗时间)
(2)锁的自动续期:若是业务超长,运行期间自动给锁上新的 30s,不用担心业务时间过长,锁就自动过期
(3)加锁的业务只要运行完成,就不会给当前锁续期,及时不手动解锁,锁默认在30s 后自动删除。
指定时间 lock() 小结
问题:在锁到期的时候,不会自动续期。
(1)如果我们传递了锁的超时时间,就发送给 redis执行脚本,进行占锁,默认的超时时间既我们指的时间
(2)若是未指定锁的超时时间,就使用 30*1000【LockWatchdogTimeout看门狗的默认时间】
(3)只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔 10 s都会自动再次续到30s, internallockLeaseTime【看门狗时间/3s】
二、其他
1、互斥
在分布式高并发的条件下,我们最需要保证,同一时刻只能有一个线程获得锁,这是最基本的一点。

2、防止死锁
在分布式高并发的条件下,比如有个线程获得锁的同时,还没有来得及去释放锁,就因为系统故障或者其它原因使它无法执行释放锁的命令,导致其它线程都无法获得锁,造成死锁。所以分布式非常有必要设置锁的有效时间,确保系统出现故障后,在一定时间内能够主动去释放锁,避免造成死锁的情况。

你可能感兴趣的:(spring,boot,分布式,后端)