当前位置:网站首页>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);
}
}
}
边栏推荐
- Alibaba three sides: how to solve the problems of MQ message loss, duplication and backlog?
- Difference between D and C
- 深入源码剖析String类为什么不可变?(还不明白就来打我)
- 06 CP command
- [audio and video] ijkplayer player parameter description document
- 同花顺手机炒股开户安全吗?怎么办理开户呢
- Circular progress bar animation based on cashapelayer and Bezier curve
- Triangular wave spectrum of MATLAB excitation model
- View绘制流程1-View与Window的关系
- Let me show you the MySQL isolation level. What happens when two transactions operate on the same row of data at the same time?
猜你喜欢

Basic operation of (C language) files

Cmake compiling obs-studio-27.2.0

第15章 mysql用户管理

09 expr 命令

07 df 命令

Task04 | classification analysis

A bowl of noodles in a dream

深入源码剖析String类为什么不可变?(还不明白就来打我)

Let Xiaobai thoroughly understand performance tuning

Understanding and practice of the trend of Bank of London foreign exchange
随机推荐
Overview of MPLS Basics
[audio and video] ijkplayer player parameter description document
Cmake compiling obs-studio-27.2.0
【Try to Hack】防火墙(一)
iptables防止nmap扫描以及binlog实现增量备份
07 df 命令
Leetcode exercise - Sword finger offer II 005. maximum product of word length
Pytoch uses RNN model to build person name classifier
Also on Data Governance
Basic operation of (C language) files
matlab 画短时平均幅度谱
imshow()函数后面如果不加waitKey()函数就不显示
一篇让小百彻底搞懂性能调优
July training (the 26th day) - and check the collection
Ansible installation and use
View绘制流程1-View与Window的关系
AFNetworking了解
MPLS基础知识概述
Go----Go 语言中的标识符和关键字
仅需一个依赖给Swagger换上新皮肤,既简单又炫酷~