当前位置: 首页 > web >正文

一文掌握Redisson分布式锁

简介

Redisson 说白了就是redis的儿子,本质上还是对redis进行加锁,不过是对redis进行了很多封装,他不仅仅提供了一系列的分布式的Java常用对象,还提供了许多的分布式服务。

与其他产品的比较

(redis审)

  • Redisson 与 Jedis 、 Lettuce 有什么区别。
  1. Redisson和他俩的区别就像一个用鼠标操作图形化界面 , 一个用命令行操作文件夹,Redisson是更高层的抽象,Jedis和Lettuce是Redis命令的封装。
  2. Jedis是Redis官方推出的用于通过Java连接Redis客户端的一个工具包,提供了Redis的各种命令支持
  3. Lettuce是一种可扩展的线程安全的 Redis 客户端,通讯框架基于Netty,支持高级的 Redis 特性,比如哨兵,集群,管道,自动重新连接和Redis数据模型。Spring Boot 2.x 开始 Lettuce 已取代 Jedis 成为首选 Redis 的客户端。
  4. Redisson是架设在Redis基础上,通讯基于Netty的综合的、新型的中间件,企业级开发中使用Redis的最佳范本
  5. Jedis把Redis命令封装好,Lettuce则进一步有了更丰富的Api,也支持集群等模式。但是两者只给了你操作Redis数据库的脚手架,而Redisson则是基于Redis、Lua和Netty建立起了成熟的分布式解决方案,甚至redis官方都推荐的一种工具集

Redisson 操作使用

引入pom.xml依赖

在引入 Redisson 的依赖后 , 就可以直接调用了.

<!-- 原生 -->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.13.4</version>
</dependency>

项目中,增加配置文件

package com.example.spring_boot_family_meals.Redisson;import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @Date 2023/8/24 10:38*/
@Configuration
public class RedissonConfig {@Value("${spring.redis.host}")private String redisHost;@Value("${spring.redis.password}")private String password;private int port = 6379;@Beanpublic RedissonClient getRedisson() {System.out.println("初始化redisson :" + redisHost);Config config = new Config();config.useSingleServer().setAddress("redis://" + redisHost + ":" + port).setPassword(password);config.setCodec(new JsonJacksonCodec());return Redisson.create(config);}
}

启动分布式锁 (项目示例)

package com.example.spring_boot_family_meals.Redisson;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 javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;@RestController
@RequestMapping("/redisson")
public class RedissonController {@Resourceprivate RedissonClient redissonClient;@GetMapping("/test")public String test() {
//      1 : 创建线程 : 执行业务 1new Thread(() -> business_1()).start();
//      2 : 创建线程 : 执行业务 2new Thread(() -> business_2()).start();
//      3 : 创建线程 : 执行业务 3new Thread(() -> business_3()).start();return "ok";}/*** 业务一 : 对缓存进行加锁,锁过期10分钟 :业务睡眠10秒*/public void business_1() {
//      1 : 获取锁RLock rLock = redissonClient.getLock("business");System.out.println(getDate() + " : business_1 : 锁获取成功");try {
//          1.1 : 加锁,指定锁过期的时间 1分钟boolean isLocked = rLock.tryLock(10, TimeUnit.MINUTES);System.out.println(getDate() + " : business_1 : 加锁成功");if (isLocked) {
//          1.2 : 开始执行逻辑(我们这里睡眠)System.out.println(getDate() + " : business_1 : 开始执行业务逻辑");Thread.sleep(10000); //睡眠十秒System.out.println(getDate() + " : business_1 : 结束执行业务逻辑");}} catch (Exception e) {e.printStackTrace();} finally {System.out.println(getDate() + " : business_1 : 释放锁");rLock.unlock();}}/*** 业务二 : 对缓存进行加锁,锁过期 1 分钟 : 业务睡眠一百秒*/public void business_2() {
//      1 : 获取锁RLock rLock = redissonClient.getLock("business");System.out.println(getDate() + " : business_2 : 锁获取成功");try {
//          1.1 : 加锁,指定锁过期的时间 1分钟boolean isLocked = rLock.tryLock(1, TimeUnit.MINUTES);System.out.println(getDate() + " : business_2 : 加锁成功");if (isLocked) {
//          1.2 : 开始执行逻辑(我们这里睡眠)System.out.println(getDate() + " : business_2 : 开始执行业务逻辑");Thread.sleep(100000); // 睡眠100秒System.out.println(getDate() + " : business_2 : 结束执行业务逻辑");}} catch (Exception e) {e.printStackTrace();} finally {System.out.println(getDate() + " : business_2 : 释放锁");rLock.unlock();}}/*** 业务三 : 对缓存进行加锁,锁过期 1 分钟 : 业务睡眠 10 百秒*/public void business_3() {
//      1 : 获取锁RLock rLock = redissonClient.getLock("business");System.out.println(getDate() + " : business_3 : 锁获取成功");try {
//          1.1 : 加锁,指定锁过期的时间 1分钟boolean isLocked = rLock.tryLock(1, TimeUnit.MINUTES);System.out.println(getDate() + " : business_3 : 加锁成功");if (isLocked) {
//          1.2 : 开始执行逻辑(我们这里睡眠)System.out.println(getDate() + " : business_3 : 开始执行业务逻辑");Thread.sleep(10000); // 睡眠十秒System.out.println(getDate() + " : business_3 : 结束执行业务逻辑");}} catch (Exception e) {e.printStackTrace();} finally {System.out.println(getDate() + " : business_3 : 释放锁");rLock.unlock();}}/*** 获取到当前时分秒*/public static String getDate() {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String format = dateFormat.format(new Date());return format;}}
  • 执行结果 :
#  Rediss项目启动,初始化成功
初始化redisson :127.0.0.1
2023-08-24 11:19:23.945  INFO 10100 --- [           main] org.redisson.Version                     : Redisson 3.15.5
2023-08-24 11:19:24.759  INFO 10100 --- [sson-netty-2-13] o.r.c.pool.MasterPubSubConnectionPool    : 1 connections initialized for /127.0.0.1:6379
2023-08-24 11:19:25.201  INFO 10100 --- [sson-netty-2-19] o.r.c.pool.MasterConnectionPool          : 24 connections initialized for /127.0.0.1:6379
2023-08-24 11:19:25.471  INFO 10100 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-08-24 11:19:25.479  INFO 10100 --- [           main] c.e.springtest.SpringTestApplication     : Started SpringTestApplication in 2.611 seconds (JVM running for 3.276)
2023-08-24 11:19:33.530  INFO 10100 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-08-24 11:19:33.530  INFO 10100 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2023-08-24 11:19:33.534  INFO 10100 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
# 3个线程同时争夺一把锁
2023-08-24 11:19:33 : business_2 : 锁获取成功
2023-08-24 11:19:33 : business_3 : 锁获取成功
2023-08-24 11:19:33 : business_1 : 锁获取成功
# 业务3 抢锁成功
2023-08-24 11:19:41 : business_3 : 加锁成功
2023-08-24 11:19:41 : business_3 : 开始执行业务逻辑
2023-08-24 11:19:51 : business_3 : 结束执行业务逻辑
2023-08-24 11:19:51 : business_3 : 释放锁
# 业务3 释放锁 ,业务1抢锁
2023-08-24 11:19:51 : business_1 : 加锁成功
2023-08-24 11:19:51 : business_1 : 开始执行业务逻辑
2023-08-24 11:20:01 : business_1 : 结束执行业务逻辑
2023-08-24 11:20:01 : business_1 : 释放锁
# 业务1 释放所 , 业务2抢锁
2023-08-24 11:20:02 : business_2 : 加锁成功
2023-08-24 11:20:02 : business_2 : 开始执行业务逻辑
2023-08-24 11:21:42 : business_2 : 结束执行业务逻辑
2023-08-24 11:21:42 : business_2 : 释放锁

下面是缓存中存放的内容
在这里插入图片描述

Redisson原理讲解

以上的代码简单明了 , 三个线程模拟三个服务来争抢一把锁, 我们只需要一个 Rlock ,下面我们来看看Redisson是怎么实现的

Redisson与使用JDK的ReentrantLock差不多 , 并且也支持并且也支持 ReadWriteLock(读写锁)、Reentrant Lock(可重入锁)、Fair Lock(公平锁)、RedLock(红锁)等各种锁,详细可以参照redisson官方文档来查看。

那么 Redisson到底有哪些优势呢? 锁的自动续期 (默认都是30秒) , 如果业务超长,运行期间会自动给锁续上新的30秒,不用担心业务执行较长而锁被自动删掉.

加锁的业务只要运行完成 , 就不会给当前续期 , 即便不手动解锁,锁默认在30秒后自动删除,不会照成死锁的原因.

前面也提到了锁的自动续期,那么我们来看看Redisson是怎么实现的


The end.

http://www.xdnf.cn/news/20027.html

相关文章:

  • 【Rhino】【Python】将开放曲面转换为边界线和填充
  • [特殊字符] DA1-13 复习学习笔记
  • 极空间打造 “超级中枢”,从书签笔记到聊天分享,一键全搞定!
  • 非力扣100原题
  • FTL文件格式的原理与应用(AI)
  • AI歌手功能终于上线!Suno AI 带你保存歌曲的灵魂
  • 【教程】2025 IDEA 快速创建springboot(maven)项目
  • spring boot autoconfigure 自动配置的类,和手工 @configuration + @bean 本质区别
  • 硬件开发1-51单片机2-按键、中断
  • 域名不做网站使用,还需要备案吗
  • 这才是真正懂C/C++的人,写代码时怎么区分函数指针和指针函数?
  • Qt + windows + Linux+QtInstallerFramework打包教程
  • RabbitMQ相关知识
  • 基于 STM32N6-AI Image Classification 使用 git bash 命令行示例 LAT1552
  • 单片机点灯
  • 【C++上岸】C++常见面试题目--算法篇(第十八期)
  • 网络:tcp
  • 关于稳定币的一些问答
  • 封装一个redis获取并解析数据的工具类
  • FPGA学习笔记——SDR SDRAM简介
  • 【golang长途旅行第37站】Redis连接池
  • OCR 发票识别与验真接口:助力电子化发票新时代
  • 融云:当我们谈论 AI 重构业务时,我们到底在谈论什么
  • 【Android】SharedPreferences轻量级持久化存储
  • 【题解】洛谷P1776 宝物筛选 [单调队列优化多重背包]
  • C++----模板特化以及模板声明与定义分离问题
  • AT32网线拔插下,modbus tcp断线重连
  • Linux awk命令完全指南:从原理到实战,搞定文本处理难题
  • 【AI】人工智能 传统和现代 架构和算法的演变历史
  • windows安装谷歌浏览器地址