当前位置:网站首页>Redis distributed lock + Lua atomic operation
Redis distributed lock + Lua atomic operation
2022-07-26 22:12:00 【weixin_ thirty-nine million five hundred and five thousand and 】
package com.example.demo.redis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.exceptions.JedisNoScriptException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class RedisLockUtil {
// Distributed lock related fields
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";
private static final Long RELEASE_SUCCESS = 1L;
private static final Long UNLOCK_SUCCESS_CODE = 1L;
private volatile String unlockSha1 = "";
private static final Logger logger = LoggerFactory.getLogger(RedisLockUtil.class);
/** * adopt lua Script release lock , To achieve the atomic operation of releasing the lock * Judge whether the lock value is held by the current thread , Unlock if yes , If not, unlocking fails */
String UNLOCK_LUA = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
@Autowired
private JedisCluster jedisCluster;
/** * according to loopTryTime Loop retry * @param lockKey lock key * @param lockVal Lock value , Used for unlocking verification * @param expiryTime Lock expiration time * @param loopTryTime When get fails , The length of time to cycle and retry to acquire the lock * @return Whether to obtain the lock */
public boolean tryLock(String lockKey, String lockVal, long expiryTime, long loopTryTime){
Long endTime = System.currentTimeMillis() + loopTryTime;
while (System.currentTimeMillis() < endTime){
if (tryGetDistributedLock(lockKey, lockVal, expiryTime)){
return true;
}
}
return false;
}
/** * Try to get distributed lock * @param lockKey lock * @param requestId The request id * @param expireTime Beyond the time * @return Success or failure */
public Boolean tryGetDistributedLock(String lockKey, String requestId, long expireTime) {
String result = jedisCluster.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
/** * Release distributed lock * @param lockKey lock * @param requestId The request id * @return Whether to release successfully */
public Boolean tryUnLockEval(String lockKey, String requestId) {
Object result = jedisCluster.eval(UNLOCK_LUA, Collections.singletonList(lockKey), Collections.singletonList(requestId));
if (RELEASE_SUCCESS.equals(result)) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
/** * Release distributed lock , The most likely reason for release failure is that the business execution time is longer than lockKey Expiration time , The expiration time should be adjusted according to the business scenario * @param lockKey lock key * @param lockVal Lock value * @return Whether to release successfully */
public boolean tryUnLockEvalsha(String lockKey, String lockVal){
List<String> keys = new ArrayList<>();
keys.add(lockKey);
List<String> argv = new ArrayList<>();
argv.add(lockVal);
try {
Object result = jedisCluster.evalsha(unlockSha1, keys, argv);
return UNLOCK_SUCCESS_CODE.equals(result);
} catch (JedisNoScriptException e){
// When there is no script cache , Resend cache
logger.info("try to store script......");
storeScript(lockKey);
Object result = jedisCluster.evalsha(unlockSha1, keys, argv);
return UNLOCK_SUCCESS_CODE.equals(result);
} catch (Exception e){
logger.info(e.getMessage());
return false;
}
}
/** * Due to the use redis colony , Therefore, each node needs to cache a copy of script data * @param slotKey Used to locate the corresponding slot Of slotKey */
public void storeScript(String slotKey){
if (StringUtils.isEmpty(unlockSha1) || !jedisCluster.scriptExists(unlockSha1, slotKey)){
//redis Support script caching , Return hash code , Later, it can be used to call scripts
unlockSha1 = jedisCluster.scriptLoad(UNLOCK_LUA, slotKey);
}
}
}
边栏推荐
- EasyUI DataGrid obtains multiple selected data for operation
- TASK04|分类分析
- Oppo self-developed large-scale knowledge map and its application in digital intelligence engineering
- xshell7个人免费下载,使用
- 同花顺手机炒股开户安全吗?怎么办理开户呢
- Development to testing: a six-year road to automation from scratch
- AFNetworking了解
- JS verify complex password
- Open source | arex Ctrip traffic playback practice without code intrusion
- 开发转测试:从零开始的6年自动化之路
猜你喜欢

Triangular wave spectrum of MATLAB excitation model

JS delay execution window.onload

xshell7个人免费下载,使用

Just one dependency to give swagger a new skin, which is simple and cool

JS 延迟执行window.onload

Isilon's onefs common operation commands (I)
![[shutter -- geTx] pop up - dialog, snackBar, bottomsheet](/img/17/af2e45620e96a78235081145b7bb76.png)
[shutter -- geTx] pop up - dialog, snackBar, bottomsheet

JDBC operation and entry case of MySQL

day07-

第15章 mysql用户管理
随机推荐
Circular progress bar animation based on cashapelayer and Bezier curve
imshow()函数后面如果不加waitKey()函数就不显示
matlab 画短时能量图
同花顺手机炒股开户安全吗?怎么办理开户呢
07 DF command
Unity对资源管理器操作 打开资源管理器选择文件并筛选文件
深入源码剖析String类为什么不可变?(还不明白就来打我)
Go --- identifiers and keywords in go language
Let Xiaobai thoroughly understand performance tuning
07 df 命令
开发转测试:从零开始的6年自动化之路
Promise me, don't write shit code after reading it..
06 cp 命令
Operating guidelines and suggestions for spot gold (Part 1)
第15章 mysql用户管理
梦里的一碗面
Development to testing: a six-year road to automation from scratch
Matlab pitch period estimation post-processing
mysql推荐书
Unity installation failed: operation not allowed, MKDIR