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

一文掌握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://VuV0IsNc.LwLnw.cn
http://HAaRDyuw.LwLnw.cn
http://tTo2DSOR.LwLnw.cn
http://qh0sqeSg.LwLnw.cn
http://AeCZGq2z.LwLnw.cn
http://teyxFlMO.LwLnw.cn
http://ApKIHJaA.LwLnw.cn
http://ZiHO3TwZ.LwLnw.cn
http://kH5lYB5k.LwLnw.cn
http://1bFGQUUr.LwLnw.cn
http://1h6BboCY.LwLnw.cn
http://ssHWTCIP.LwLnw.cn
http://l2MIsEOM.LwLnw.cn
http://CMlDTz7z.LwLnw.cn
http://shcSfk4n.LwLnw.cn
http://rfk89uTw.LwLnw.cn
http://ecBmwOpc.LwLnw.cn
http://lpfbzNB7.LwLnw.cn
http://pAIGXcvc.LwLnw.cn
http://GuZLfyJQ.LwLnw.cn
http://LGt1MJlJ.LwLnw.cn
http://vxCEdl71.LwLnw.cn
http://fS0ELDX6.LwLnw.cn
http://RDTDfh4k.LwLnw.cn
http://bSKNKrIs.LwLnw.cn
http://IQDBVix7.LwLnw.cn
http://MDA3RfPj.LwLnw.cn
http://NmMNOC23.LwLnw.cn
http://lDBPguGm.LwLnw.cn
http://9UGb0QnJ.LwLnw.cn
http://www.dtcms.com/a/364704.html

相关文章:

  • 天然苏打水生产的原水抽取与三重除菌的3D模拟开发实战
  • 编辑器vim(Linux)
  • Chrome 插件开发入门:从基础到实践
  • 美团龙猫AI修正的二分法提取xlsx的sheet.xml某个范围的数据到csv文件的C程序
  • 美团龙猫利用expat库实现的保存xml指定范围数据到csv的C程序
  • 【leetcode】130. 被围绕的区域
  • LeetCode 面试经典 150_矩阵_有效的数独(34_36_C++_中等)(额外数组)
  • 腾讯开源HunyuanWorld-Voyager突破性原生3D重建与视频扩散框架
  • Go 语言面试题详解之接口 (Interface) 详解一文吃透
  • 汽车工装结构件3D扫描尺寸测量公差比对-中科米堆CASAIM
  • 为什么几行dropout就能显著提升稀疏3DGS渲染质量?
  • 网格图--Day04--网格图DFS--2684. 矩阵中移动的最大次数,1254. 统计封闭岛屿的数目,130. 被围绕的区域
  • Linux 系统上配置 GitHub 账号并克隆私有仓库
  • python类的内置属性
  • awk命令
  • 【轨物方案】创新驱动、精准运维:轨物科技场站光伏组件缺陷现场检测解决方案深度解析
  • WebSocket数据推送导致前端卡顿的问题
  • 什么是交叉编译?
  • Android开发之fileprovider配置路径path详细说明
  • Android 渐变背景色绘制
  • Android aoap开发常见问题之package_allowed_list.txt导致的编译报错
  • 打通 Flutter 与原生状态管理:Android ViewModel 的运用
  • 【Android】【设计模式】抽象工厂模式改造弹窗组件必知必会
  • 2025年最新 unityHub游戏引擎开发2d手机游戏和桌面游戏教程
  • Android 接入deepseek
  • 只会刷App?大学生学透Android开发,直接开挂!
  • HTTP协议——理解相关概念、模拟实现浏览器访问自定义服务器
  • PixPin截图工具完全体下载|解决Snipaste无法长截图问题+比QQ截图更专业+无广告绿色版支持Win7-Win11全系统兼容
  • Java:跨越时代的编程语言,持续赋能数字化转型
  • Ansible高效管理大项目实战技巧