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

Redisson 分布式锁原理分析

Redisson 分布式锁原理分析

示例程序

示例程序:

public class RedissonTest {public static void main(String[] args) {Config config = new Config();config.useSingleServer().setPassword("123456").setAddress("redis://127.0.0.1:6379");RedissonClient redisson = Redisson.create(config);// RLock对象RLock lock = redisson.getLock("MY_KEY");ExecutorService pool = Executors.newFixedThreadPool(5);IntStream.range(1, 5).forEach(item -> {pool.execute(() -> {try {if (lock.tryLock(2000, TimeUnit.MILLISECONDS)) {System.out.println(Thread.currentThread().getName() + "get Lock!!");if (lock.tryLock(2000, TimeUnit.MILLISECONDS)) {System.out.println(Thread.currentThread().getName() + "get Lock!!");Thread.sleep(300000);lock.unlock();}Thread.sleep(500000);lock.unlock();}} catch (Exception e) {System.out.println("error!!");}});});}
}

运行结果:
image.png

redis中的值:
image.png

原理

分布式锁实现加锁解锁都需要使用lua脚本。
利用Redis的Hash结构实现可重入。

Hash结构存值如下:

keyfieldvalue
  • key:就是分布式锁的key
  • field:用于存储一个能够表示一个线程的唯一标识(Redisson使用的UUID)
  • value:表示当前锁被同一个线程加锁的次数(可重入的实现方式)

下面以key为MY_KEY,field线程唯一标识为:WWSSWWWKKII99I为例,总结下加锁解锁流程:

加锁流程

加锁流程:

加锁之后,hash结构为

keyfieldvalue
MY_KEYWWSSWWWKKII99I1

实际的存储示例:
一个线程获取了一次:
image.png
一个线程获取了两次(可重入):
image.png

解锁流程

解锁流程:
假设当前锁的hash结构是

keyfieldvalue
MY_KEYWWSSWWWKKII99I2

这代表分布式锁 MY_KEY 被线程标识为 WWSSWWWKKII99I 的线程获取了两次

需要注意,整个加锁解锁的命令全都需要使用lua脚本。这样能保证操作的原子性。

相关文章:

  • 智能合约 之 ERC-20介绍
  • vue-admin-template极简的 vue admin 管理后台的动态路由实现方法
  • 002_avoid_for_loop_in_Matlab避免使用for循环
  • Session、Cookie 和 Token的保存
  • 【蓝桥杯选拔赛真题72】python输出整数 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析
  • 软件测试教程 自动化测试之Junit框架
  • 网络安全进入AI赋能时代
  • 记录C++中,子类同名属性并不能完全覆盖父类属性的问题
  • Linux编程3.8 进程-守护进程
  • nodejs中使用@maxmind/geoip2-node 查询地理位置信息
  • MySQL的进阶使用方法
  • 3D开发工具HOOPS如何助力3D项目实现扩展现实技术?
  • Trait与生命周期
  • 学习vue3 第四章(reactive全家桶)
  • playwright自动化项目搭建
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • JavaScript对象详解
  • jquery cookie
  • js ES6 求数组的交集,并集,还有差集
  • JS+CSS实现数字滚动
  • JS变量作用域
  • Laravel 中的一个后期静态绑定
  • LeetCode算法系列_0891_子序列宽度之和
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • Webpack 4x 之路 ( 四 )
  • 每天10道Java面试题,跟我走,offer有!
  • 前端自动化解决方案
  • 深入浅出webpack学习(1)--核心概念
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 延迟脚本的方式
  • 由插件封装引出的一丢丢思考
  • Prometheus VS InfluxDB
  • ​插件化DPI在商用WIFI中的价值
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (003)SlickEdit Unity的补全
  • (02)vite环境变量配置
  • (12)Linux 常见的三种进程状态
  • (C#)获取字符编码的类
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (附源码)ssm码农论坛 毕业设计 231126
  • (附源码)计算机毕业设计大学生兼职系统
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (四)linux文件内容查看
  • (转)ORM
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .mysql secret在哪_MySQL如何使用索引
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .net 生成二级域名
  • ??javascript里的变量问题