目录

  • 项目结构
    • pom.xml
    • application.yml
    • RedissonProperties
    • RedissonAutoConfiguration
    • DistributedLocker
    • RedissonDistributedLocker
    • RedissonLockUtil
    • RedissonLockApplication
    • TestController
  • 测试结果
  • Redisson分布式锁原理

源码见gitee
链接: https://gitee.com/qiu_yunzhao/distributed_lock.

项目结构

pom.xml

依赖

<?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.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.haoqian</groupId><artifactId>redission_lock</artifactId><version>0.0.1-SNAPSHOT</version><name>redission_lock</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.13.6</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.yml

配置文件

redisson:# 单机address: 127.0.0.1:6931password: aaaaaadatabase: 10#  # 哨兵集群
#  master-name: mymaster
#  password: aaaaaa
#  sentinel-addresses:
#    - 10.47.91.83:26379
#    - 10.47.91.83:26380
#    - 10.47.91.83:26381

RedissonProperties

redisson配置文件的装配类

package com.haoqian.redission_lock.config;import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "redisson")
public class RedissonProperties {private int timeout = 3000; // 连接超时时间private String address;     // 单机redis地址private String password;    // redis密码private int database = 0;   // 使用的redis库号private int connectionPoolSize = 64;  // 连接池大小private int connectionMinimumIdleSize = 10; // 连接池中的最小空闲连接private int slaveConnectionPoolSize = 250;  // 从节点连接池大小private int masterConnectionPoolSize = 250; // 主节点连接池大小private String masterName; // 主节点名称private String[] sentinelAddresses; // 集群地址public int getTimeout() {return timeout;}public void setTimeout(int timeout) {this.timeout = timeout;}public int getSlaveConnectionPoolSize() {return slaveConnectionPoolSize;}public void setSlaveConnectionPoolSize(int slaveConnectionPoolSize) {this.slaveConnectionPoolSize = slaveConnectionPoolSize;}public int getMasterConnectionPoolSize() {return masterConnectionPoolSize;}public void setMasterConnectionPoolSize(int masterConnectionPoolSize) {this.masterConnectionPoolSize = masterConnectionPoolSize;}public String[] getSentinelAddresses() {return sentinelAddresses;}public void setSentinelAddresses(String[] sentinelAddresses) {this.sentinelAddresses = sentinelAddresses;}public String getMasterName() {return masterName;}public void setMasterName(String masterName) {this.masterName = masterName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public int getDatabase() {return this.database;}public void setDatabase(int database) {this.database = database;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public int getConnectionPoolSize() {return connectionPoolSize;}public void setConnectionPoolSize(int connectionPoolSize) {this.connectionPoolSize = connectionPoolSize;}public int getConnectionMinimumIdleSize() {return connectionMinimumIdleSize;}public void setConnectionMinimumIdleSize(int connectionMinimumIdleSize) {this.connectionMinimumIdleSize = connectionMinimumIdleSize;}
}

RedissonAutoConfiguration

启动springboot是 RedissonClient 注入到spring容器,并装配工具类RedissonLockUtil

package com.haoqian.redission_lock.config;import com.haoqian.redission_lock.distributedLock.DistributedLocker;
import com.haoqian.redission_lock.distributedLock.RedissonDistributedLocker;
import com.haoqian.redission_lock.Utils.RedissonLockUtil;
import io.micrometer.core.instrument.util.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SentinelServersConfig;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ConditionalOnClass(Config.class) // org.redisson.config.Config
@EnableConfigurationProperties(RedissonProperties.class) // 自定义redisson配置类
public class RedissonAutoConfiguration {@Autowiredprivate RedissonProperties redissonProperties;/*** 哨兵模式自动装配** @return*/@Bean@ConditionalOnProperty(name = "redisson.master-name")RedissonClient redissonSentinelClient() {Config config = new Config();SentinelServersConfig serverConfig = config.useSentinelServers().addSentinelAddress(redissonProperties.getSentinelAddresses()).setMasterName(redissonProperties.getMasterName()).setTimeout(redissonProperties.getTimeout()).setMasterConnectionPoolSize(redissonProperties.getMasterConnectionPoolSize()).setSlaveConnectionPoolSize(redissonProperties.getSlaveConnectionPoolSize()).setDatabase(redissonProperties.getDatabase());if (StringUtils.isNotBlank(redissonProperties.getPassword())) {serverConfig.setPassword(redissonProperties.getPassword());}return Redisson.create(config);}/*** 单机模式自动装配** @return*/@Bean@ConditionalOnProperty(name = "redisson.address")RedissonClient redissonSingleClient() {Config config = new Config();SingleServerConfig serverConfig = config.useSingleServer().setAddress("redis://" + redissonProperties.getAddress()).setTimeout(redissonProperties.getTimeout()).setConnectionPoolSize(redissonProperties.getConnectionPoolSize()).setConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize()).setDatabase(redissonProperties.getDatabase());if (StringUtils.isNotBlank(redissonProperties.getPassword())) {serverConfig.setPassword(redissonProperties.getPassword());}return Redisson.create(config);}/*** 装配locker类,并将实例注入到 RedissLockUtil 中** @return*/@BeanDistributedLocker distributedLocker(RedissonClient redissonClient) {RedissonDistributedLocker locker = new RedissonDistributedLocker(redissonClient);RedissonLockUtil.setLocker(locker);return locker;}}

DistributedLocker

自定义封装Redisson分布式锁的lock接口

package com.haoqian.redission_lock.distributedLock;import java.util.concurrent.TimeUnit;/*** 分布式锁接口*/
public interface DistributedLocker {/*** 获取锁,如果锁不可用,则当前线程处于休眠状态,直到获得锁为止。** @param lockKey*/void lock(String lockKey);/*** 获取锁,如果锁不可用,则当前线程处于休眠状态,直到获得锁为止。* 如果获取到锁后,执行结束后调用 unlock(String lockKey) 解锁或达到超时时间后会自动释放锁* 默认时间单位是 TimeUnit.SECONDS** @param lockKey* @param leaseTime*/void lock(String lockKey, int leaseTime);/*** 获取锁,如果锁不可用,则当前线程处于休眠状态,直到获得锁为止。* 如果获取到锁后,执行结束后调用 unlock(String lockKey) 解锁或达到超时时间后会自动释放锁** @param lockKey   // 锁唯一名称* @param leaseTime // 持有锁的时间* @param unit      // 指定 leaseTime 的时间单位*/void lock(String lockKey, int leaseTime, TimeUnit unit);/*** 尝试获取锁,获取到立即返回true,未获取到立即返回false** @param lockKey* @return*/boolean tryLock(String lockKey);/*** 尝试获取锁,在等待时间内获取到锁则返回true,否则返回false,* 如果获取到锁,执行完后程序调用 unlock(String lockKey) 释放锁或在给定的超时时间leaseTime后释放锁** @param lockKey* @param waitTime  // 尝试获取锁的等待时间* @param leaseTime // 持有锁的时间* @param unit      // 指定 leaseTime 的时间单位* @return*/boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException;/*** 锁是否被任意一个线程锁持有** @param lockKey* @return*/boolean isLocked(String lockKey);/*** 释放锁** @param lockKey*/void unlock(String lockKey);
}

RedissonDistributedLocker

自定义封装Redisson分布式锁的lock接口实现类

package com.haoqian.redission_lock.distributedLock;import com.haoqian.redission_lock.distributedLock.DistributedLocker;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;import java.util.concurrent.TimeUnit;public class RedissonDistributedLocker implements DistributedLocker {private RedissonClient redissonClient;public RedissonDistributedLocker() {}public RedissonDistributedLocker(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@Overridepublic void lock(String lockKey) {RLock lock = redissonClient.getLock(lockKey);lock.lock();}@Overridepublic void lock(String lockKey, int leaseTime) {RLock lock = redissonClient.getLock(lockKey);lock.lock(leaseTime, TimeUnit.SECONDS);}@Overridepublic void lock(String lockKey, int leaseTime, TimeUnit unit) {RLock lock = redissonClient.getLock(lockKey);lock.lock(leaseTime, unit);}@Overridepublic boolean tryLock(String lockKey) {RLock lock = redissonClient.getLock(lockKey);return lock.tryLock();}@Overridepublic boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {RLock lock = redissonClient.getLock(lockKey);return lock.tryLock(waitTime, leaseTime, unit);}@Overridepublic boolean isLocked(String lockKey) {RLock lock = redissonClient.getLock(lockKey);return  lock.isLocked();}@Overridepublic void unlock(String lockKey) {RLock lock = redissonClient.getLock(lockKey);lock.unlock();}}

RedissonLockUtil

redis分布式锁工具类

package com.haoqian.redission_lock.Utils;import com.haoqian.redission_lock.distributedLock.DistributedLocker;import java.util.concurrent.TimeUnit;/*** redisson 分布式锁帮助类*/
public class RedissonLockUtil {private static DistributedLocker redissonLocker;public static void setLocker(DistributedLocker locker) {redissonLocker = locker;}/*** 获取锁** @param lockKey*/public static void lock(String lockKey) {redissonLocker.lock(lockKey);}/*** 获取锁,超时释放** @param lockKey* @param leaseTime 持有锁的时间(单位:秒)*/public static void lock(String lockKey, int leaseTime) {redissonLocker.lock(lockKey, leaseTime);}/*** 获取锁,超时释放,指定时间单位** @param lockKey* @param leaseTime 持有锁的时间* @param unit      leaseTime的单位*/public static void lock(String lockKey, int leaseTime, TimeUnit unit) {redissonLocker.lock(lockKey, leaseTime, unit);}/*** 尝试获取锁,获取到立即返回true,获取失败立即返回false** @param lockKey* @return*/public static boolean tryLock(String lockKey) {return redissonLocker.tryLock(lockKey);}/*** 尝试获取锁,在给定的waitTime时间内尝试,获取到返回true,获取失败返回false,获取到后再给定的leaseTime时间超时释放** @param lockKey* @param waitTime* @param leaseTime* @param unit* @return* @throws InterruptedException*/public static boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {return redissonLocker.tryLock(lockKey, waitTime, leaseTime, unit);}/*** 锁是否被任意一个线程锁持有** @param lockKey* @return*/public static boolean isLocked(String lockKey) {return redissonLocker.isLocked(lockKey);}/*** 解锁** @param lockKey*/public static void unlock(String lockKey) {redissonLocker.unlock(lockKey);}
}

RedissonLockApplication

主启动类

package com.haoqian.redission_lock;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class RedissonLockApplication {public static void main(String[] args) {SpringApplication.run(RedissonLockApplication.class, args);}}

TestController

测试类

package com.haoqian.redission_lock.controller;import com.haoqian.redission_lock.Utils.RedissonLockUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.TimeUnit;@RestController
public class TestController {/*** lock 会阻塞知道获取到锁*/@GetMapping("/testLock1")public void testLock1() {for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {RedissonLockUtil.lock("RedissonLock");System.out.println(Thread.currentThread().getName() + "获取到锁");} catch (Exception e) {e.printStackTrace();} finally {RedissonLockUtil.unlock("RedissonLock");System.out.println(Thread.currentThread().getName() + "释放锁");}}}).start();}}/*** tryLock* 1. 获取到锁后超过leaseTime会自动释放锁* 2. 超过waitTime未获取到锁会返回false放弃获取锁*/@GetMapping("/testLock2")public void testLock2() {for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {boolean result = RedissonLockUtil.tryLock("Lock:lock2", 3, 2, TimeUnit.SECONDS);System.out.println(Thread.currentThread().getName() + "是否获取到锁" + result);} catch (Exception e) {e.printStackTrace();} finally {}}}).start();}}/*** 获取几次要释放几次,否则会阻塞*/@GetMapping("/testLock3")public void testLock3() {for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {try {RedissonLockUtil.lock("RedissonLock");RedissonLockUtil.lock("RedissonLock");System.out.println(Thread.currentThread().getName() + "获取到锁");} catch (Exception e) {e.printStackTrace();} finally {RedissonLockUtil.unlock("RedissonLock");// RedissonLockUtil.unlock("RedissonLock");System.out.println(Thread.currentThread().getName() + "释放锁");}}}).start();}}}

测试结果

http://localhost:8080/testLock1 接口测试结果:

http://localhost:8080/testLock2 接口测试结果:

http://localhost:8080/testLock3 接口测试结果:

Redisson分布式锁原理

获取锁的过程就是向redis中插入指定的key;

释放锁的过程就是清除redis中已经插入的指定的key

如果获取锁的时候redis中已经存在相同的key说明有线程已经获取了锁,不能对资源进行操作;

如果获取锁的时候redis中不存在相同的key说明没有线程获取到锁,可以对资源进行操作;

如果对redisson的原理感兴趣,可以参考我写的另一篇文章
链接: https://blog.csdn.net/QiuHaoqian/article/details/114311189.

SpringBoot+Redisson实现分布式锁相关推荐

  1. java设计前期工作基础和存在的困难_Java秒杀系统实战系列-基于Redisson的分布式锁优化秒杀逻辑...

    本文是"Java秒杀系统实战系列文章"的第十五篇,本文我们将借助综合中间件Redisson优化"秒杀系统中秒杀的核心业务逻辑",解决Redis的原子操作在优化秒 ...

  2. Java秒杀系统实战系列~基于Redisson的分布式锁优化秒杀逻辑

    摘要: 本篇博文是"Java秒杀系统实战系列文章"的第十五篇,本文我们将借助综合中间件Redisson优化"秒杀系统中秒杀的核心业务逻辑",解决Redis的原子 ...

  3. springboot整合Redis分布式锁最佳实践

    什么是分布式锁 在单机环境中,一般在多并发多线程场景下,出现多个线程去抢占一个资源,这个时候会出现线程同步问题,造成执行的结果没有达到预期.我们会用线程间加锁的方式,比如synchronized,lo ...

  4. redisson的锁的类型_绝对干货:利用redisson完成分布式锁功能

    在单体架构中,我们使用synchronize或者Lock就能完成上锁同步的操作,但是这些在分布式,微服务的今天,失去了作用. 分布式锁的实现一般有三种解决方案:基于数据库表实现 基于缓存实现,比如re ...

  5. 聊聊redisson的分布式锁

    序 本文主要研究一下redisson的分布式锁 maven <dependency><groupId>org.redisson</groupId><artif ...

  6. 22-09-20 西安 谷粒商城(04)Redisson做分布式锁、布隆过滤器、AOP赋能、自定义注解做缓存管理、秒杀测试

    Redisson 1.Redisson做分布式锁  分布式锁主流的实现方案: 基于数据库实现分布式锁 基于缓存(Redis),性能最高 基于Zookeeper,可靠性最高 Redisson是一个在Re ...

  7. Redisson实现分布式锁原理

    Redisson实现分布式锁原理 一.高效分布式锁 当我们在设计分布式锁的时候,我们应该考虑分布式锁至少要满足的一些条件,同时考虑如何高效的设计分布式锁,这里我认为以下几点是必须要考虑的. 1.互斥 ...

  8. Redisson实现分布式锁(3)—项目落地实现

    Redisson实现分布式锁(3)-项目落地实现 有关Redisson实现分布式锁前面写了两篇博客作为该项目落地的铺垫. 1.Redisson实现分布式锁(1)-原理 2.Redisson实现分布式锁 ...

  9. SpringBoot实战实现分布式锁一之重现多线程高并发场景

    实战前言:上篇博文我总体介绍了我这套视频课程:"SpringBoot实战实现分布式锁" 总体涉及的内容,从本篇文章开始,我将开始介绍其中涉及到的相关知识要点,感兴趣的小伙伴可以关注 ...

最新文章

  1. android自定义布局的使用!
  2. 8. An Introduction to MCMC for Machine Learning (3)
  3. 从 ELK 到 EFK 演进
  4. Matlab 坐标轴比例一致导致图形变形
  5. Py之imblearn:imblearn/imbalanced-learn库的简介、安装、使用方法之详细攻略
  6. php 发送短信 sms,php 调用百度sms来发送短信的实现示例
  7. 超好看的动态流量卡官网源码多功能集成式源码
  8. Java web后台插入数据库中文乱码问题解决
  9. 学习中科院杨力祥c++
  10. Windows XP几个版本的区分
  11. python爬虫框架论文开题报告范文_研究思路及框架--开题报告
  12. 单体架构常用注解合集
  13. visual c 2008 php,十步之遥顺利升级到Visual Studio 2008
  14. 获取上传文件的后缀,.jpg,.png,.word,.xsl...使用方法split,lastindexOf,subtr
  15. 【C++11】包装器
  16. 4.5 GPO的编辑
  17. python ip动态代理_Python实现爬取可用代理IP
  18. SoapUI的一些基本设置
  19. 用python爬取网站_「自如网」关于用python爬取自如网信息的价格问题(已解决) - seo实验室...
  20. 简谈新人工作之余成长的实施方案

热门文章

  1. 基于FPGA的OV5640上电时序的控制
  2. 【100%通过率】华为OD机试真题 C++ 实现【组合出合法最小数】【2023 Q1 | 100分】
  3. Linux之系统时间同步
  4. android项目 之 来电管家(3) ----- 添加与删除黑名单
  5. 使用树莓派控制舵机MG90D
  6. 【品牌DTC增长力】如何实现超级转化率+小红书操盘指南
  7. 【Appium】基础之原生App/Web App/混合App
  8. vue跨域实现与原理(proxyTable)
  9. 义务教育学校计算机师机比,海南义务教育办学基本标准试行 小学每班限45人
  10. FZU Problem 2082 过路费