前言
如果是单应用部署,直接通过synchronized关键字修改方法,就能解决,但是如果是分布式的部署
该方法就不能解决这个问题啦,此时就引出了一个分布式锁的概念。
常用的分布式锁的实现方式有三种:
- 基于数据库乐观锁(CAS)来实现
- 基于 Redis 来实现
- 基于 ZooKeeper 来实现
二、执行流程
加锁和删除锁的操作,使用纯 Lua 进行封装,保障其执行时候的原子性。
基于纯Lua脚本实现分布式锁的执行流程,大致如下:本文是lua与redis结合使用
一、示例
@AllArgsConstructor
public class JedisCommandLock {
private static final Long RELEASE_SUCCESS = 1L;
/**
* 功能:释放分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @return 是否释放成功
*/
public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
// Lua 脚本,将判断锁和释放锁变为一步操作
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
// eval()方法,是将Lua代码交给Redis服务端执行
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
return RELEASE_SUCCESS.equals(result);
}
}
那么这段 Lua 代码的功能是什么呢?
其实很简单,首先获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁(解锁)。虽然看似做了两件事,但是却只有一个完整的原子操作。
第一行代码,我们写了一个简单的 Lua 脚本代码;
第二行代码,我们将Lua代码传到 jedis.eval()方法里,并使参数 KEYS[1] 赋值为 lockKey,ARGV[1] 赋值为 requestId,eval() 方法是将Lua代码交给 Redis 服务端执行。
二、执行流程
加锁和删除锁的操作,使用纯 Lua 进行封装,保障其执行时候的原子性。
基于纯Lua脚本实现分布式锁的执行流程,大致如下: