前言:
分布式技术提升了系统的运行效率,但是也产生了新的问题(如分布式锁、全局唯一序列等)
这些问题不能直接用Java原生的技术解决,但在分布式系统中却不可或缺
Distributor基于Redis实现常用的分布式组件(如分布式锁、分布式序列、分布式限流等),简单、可靠、开箱即用
实现Redis的分布式锁主要通过lua脚本,既简单又安全
完整项目地址 https://gitee.com/HappyChicken/Distributor 麻烦大家顺手给个Star~
这里给出分布式锁的核心代码段供参考:
- 提前定义好Redis命令中需要的字符串以及默认过期时间
// Redis命令常用字符串
private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";
// 默认锁过期时间 10s
private int lockTimeout = 10000;
// 重试时间 0.5s
private int retryAwait = 500;
- 加锁(本质是在Redis中设置一个有过期时间的Key,如果加锁成功会返回这个Key对应的value,
用于解锁)
// 尝试加锁,可以指定尝试时间
@Override
public String tryLock(long tryLockTime, TimeUnit timeUnit) {
// 是否死循环获取锁
boolean forever = tryLockTime < 0;
// 开始获取锁的时间
final long startMillis = System.currentTimeMillis();
// 转为秒
final Long millisToWait = (timeUnit != null) ? timeUnit.toMillis(tryLockTime) : 0;
String lockSuccess = null;
// 如果没有加锁成功,循环尝试获取锁
while (lockSuccess == null) {
lockSuccess = doLock();
// 获取成功 退出
if (lockSuccess != null) {
break;
}
// 如果超过了获取锁的最长时间,退出
if (!forever && System.currentTimeMillis() - startMillis - retryAwait > millisToWait) {
break;
}
// 睡眠重试时间,避免太频繁的重试
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(retryAwait));
}
return lockSuccess;
}
private String doLock() {
// value值是一个随机UUID
String lockId = IdUtils.getUUID("");
Jedis jedis = null;
try {
// 获得jedis连接
jedis = getJedis();
// 尝试加锁,如果成功返回OK
// 5个参数:key value (NX)key不存在才设置 (PX)设置过期时间 过期时间
String result = getJedis().set(getKey(), lockId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME
lockTimeout);
// 加锁成功返回value值,用于解锁
return LOCK_SUCCESS.equals(result) ? lockId : null;
} finally {
//关闭连接
jedis.close();
}
}
- 解锁(传入加锁成功返回的lockId进行解锁,关键在于lua脚本的编写)
public void unLock(String lockId) {
// 如果get key的值和预期一样 就删除该key,保证由加锁的人来解锁
String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] " +
"then return redis.call('del', KEYS[1]) else return -1 end";
Jedis jedis = null;
try {
// 获得连接
jedis = getJedis();
// 执行lua脚本
jedis.eval(luaScript,
Collections.singletonList(getKey()), Collections.singletonList(lockId));
} finally {
// 关闭资源
jedis.close();
}
}
更多详情可以到 https://gitee.com/HappyChicken/Distributor 中查看!