Redisson 实现分布式锁
前言
Redis对于我们来说并不陌生,它是线程安全的(单线程),单机redis支撑万级,超过十万+级别并发量就需要用的Redis集群了。然而虽然并发量提升了同时也会有另外的问题,那就是数据不一致问题,这个时候我们就可以用的分布式锁,而Redisson已经帮我们实现好了,我们只要引入Redisson Jar包就行。
介绍
Redisson 不只是一个 Java Redis 客户端,它是一个以内存 Redis 服务器作为后端的处理 Java 对象 (如 java.util.List, java.util.Map, java.util.Set, java.util.concurrent.locks.Lock 等)的一个框架。
咱们这篇文章就来聊聊分布式锁这块知识,具体的来看看Redis分布式锁的实现原理。
一、要实现分布式锁需要满足那些前提条件呢
1、互斥
在高并发环境下,同一时刻只能有一个线程持有锁,这是最基本的条件
2、防止死锁
持有锁的线程发生故障或因为其他原因无法释放锁的时候,会导致其他线程都无法获得锁,从而造成死锁。这个时候我们很有必要设置锁的超时时间。确保故障期间能第一时间去释放锁,可以有效的防止死锁。
3、可重入
我们都知道ReentrantLock是可重入锁,它的特点就是:同一线程可以重复使用资源锁,有利于资源的高效利用。
二、Redisson 的原理分析
下面给大家看一段简单的使用代码片段,先直观的感受一下:
看到了吗,是不是很简单,接下来我们进去看一下实现原理。
为了更直观的理解,我画了张原理图
守护线程:有些业务逻辑处理可能不止30秒,这时我们可以开启个守护线程去扫描,如果持有锁的线程快到达超时时间,就主动去延长超时时间。
lua脚本
Lua是一个高效的轻量级脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能
优点:
- 减少网络开销,在Lua脚本中可以把多个命令放在同一个脚本中运行
- 原子操作,redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说,编写脚本的过程中无需担心会出现竞态条件
- 复用性,客户端发送的脚本会永远存储在redis中,这意味着其他客户端可以复用这一脚本来完成同样的逻辑
lua脚本参数意思
KEYS[1]代表的是你加锁的那个key,比如说:RLock lock = redisson.getLock(“myLock”); 加锁的那个锁key就是“myLock”
ARGV[1]代表的就是锁key的默认生存时间,默认30秒。
ARGV[2]代表的是加锁的客户端的ID,数据类型为Hash类型相当于我们java的 <key,<key1,value>>
:
myLock:{ "8743c9c0-0795-4907-87fd-6c719a6b4586:1" : 1 }
前面这串字符串对应意思 :myLock是锁key :{ guid(唯一标识符):” 当前线程的id ” :锁重入次数 }
这就是Redisson**分布式锁框架的实现机制。**一般我们在生产系统中,可以用Redisson框架提供的这个类库来基于redis进行分布式锁的加锁与释放锁。
还没有评论,来说两句吧...