package com.jd.common.core.lock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.stereotype.Component; import java.util.Collections; /** * <p>Description: 分布式锁RedisLock</p> * <p>Copyright: Copyright (c)2,024</p> * <p>Company: tope</p> * <P>Created Date :2024年02月13日</P> * @version 1.0 */ @Component public class RedisLock { private final static Logger log = LoggerFactory.getLogger(RedisLock.class); @Autowired RedisTemplate redisTemplate; private StringRedisSerializer argsStringSerializer = new StringRedisSerializer(); private StringRedisSerializer resultStringSerializer = new StringRedisSerializer(); private final String EXEC_RESULT = "1"; //定义获取锁的lua脚本 private final static DefaultRedisScript<String> LOCK_LUA_SCRIPT = new DefaultRedisScript<>( "if redis.call('set',KEYS[1],ARGV[1],'NX','PX',ARGV[2]) then " + "return '1' " + "else " + "return '0' " + "end" , String.class ); //定义释放锁的lua脚本 private final static DefaultRedisScript<String> UNLOCK_LUA_SCRIPT = new DefaultRedisScript<>( "if redis.call('get',KEYS[1]) == ARGV[1] then " + "return tostring(redis.call('del',KEYS[1])) " + "else " + "return '0' " + "end" , String.class ); /** * 加锁操作 * @param key Redis 锁的 key 值 * @param requestId 请求id,防止解了不该由自己解的锁 (随机生成) * @param expireTime 锁的超时时间(毫秒) * @param retryTimes 获取锁的重试次数 * @return true or false */ @SuppressWarnings("unchecked") public boolean lock(String key, String requestId, String expireTime, int retryTimes) { if (retryTimes <= 0) { retryTimes = 1; } try { int count = 0; while (true) { String result = (String) redisTemplate.execute(LOCK_LUA_SCRIPT, argsStringSerializer, resultStringSerializer, Collections.singletonList(key), requestId, expireTime); log.debug("result:{},type:{}", result, result.getClass().getName()); if (EXEC_RESULT.equals(result)) { log.info("lock---->result:{},requestId:{}", "加锁成功", requestId); return true; } else { count++; if (retryTimes == count) { log.warn("has tried {} times , failed to acquire lock for key:{},requestId:{}", count, key, requestId); return false; } else { log.warn("try to acquire lock {} times for key:{},requestId:{}", count, key, requestId); Thread.sleep(100); continue; } } } } catch (InterruptedException e) { log.error("lock---->result:{},requestId:{}", "加锁异常", requestId); } return false; } /** * 解锁操作 * @param key Redis 锁的 key 值 * @param requestId 请求 id, 防止解了不该由自己解的锁 (随机生成) * @return true or false */ @SuppressWarnings("unchecked") public boolean unLock(String key, String requestId) { String result = (String) redisTemplate.execute(UNLOCK_LUA_SCRIPT, argsStringSerializer, resultStringSerializer, Collections.singletonList(key), requestId); if (EXEC_RESULT.equals(result)) { log.info("unLock---->result:{},requestId:{}", "解锁成功", requestId); return true; } return false; } }
Redis工具组件Lua脚本实现
蜗牛杨哥2024-03-19 12:47
相关推荐
running up that hill4 分钟前
数据库中的增删改查操作、聚合函数、内置函数、分组查询凌虚(失业了求个工作)19 分钟前
RAG 示例:使用 langchain、Redis、llama.cpp 构建一个 kubernetes 知识库问答莳花微语21 分钟前
oracle如何配置第二个监听优化数据传输小码的头发丝、23 分钟前
Maven的安装与配置0zxm28 分钟前
01.Django快速入门在路上走着走着38 分钟前
clickhouse数据库,http请求访问,支持参数化2的n次方_41 分钟前
MyBatis Plus 项目的创建和使用张彦峰ZYF1 小时前
解读InnoDB数据库索引页与数据行的紧密关联武子康1 小时前
Java-08 深入浅出 MyBatis - 多对多模型 SqlMapConfig 与 Mapper 详细讲解测试荼靡6032 小时前
shell(三)