Redis分布式锁
直接上代码

package xxx.xxx.common.utils; import lombok.extern.slf4j.Slf4j; 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.core.script.RedisScript; import org.springframework.stereotype.Component; import java.util.Collections; import java.util.concurrent.TimeUnit; /** * @Description: Redis分布式锁 * @author: wph * @date: 2021/11/29 */ @Component @Slf4j public class RedisLock { private static final Long SUCCESS_UNLOCK = 1L; @Autowired private RedisTemplate<String, Object> redisTemplate; /** * redis 加锁 * key 锁的key * value 锁的值,用于解锁 * expireTime 失效时间 单位:SECONDS */ public boolean tryLockForSpin(String key, String value, long expireTime, long spinTimeOut) { Long start = System.currentTimeMillis(); try { for (; ; ) { log.debug("尝试获取锁,当前线程ID{}", Thread.currentThread().getId()); boolean ret = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS); if (ret) { log.debug("获取锁成功,当前线程ID{}", Thread.currentThread().getId()); return true; } //否则循环等待,在spinTimeOut时间内仍未获取到锁,则获取失败 long end = System.currentTimeMillis() - start; if (end >= spinTimeOut) { return false; } } } catch (Exception ex) { ex.printStackTrace(); } return false; } /** * redis 加锁 * key 锁的key * value 锁的值,用于解锁 * expireTime 失效时间 单位:SECONDS * isSpin 是否需要自旋循环获取锁(未获取) * spinTimeOut 自旋的过期时间 */ public boolean tryLock(String key, String value, long expireTime,boolean isSpin,long spinTimeOut) { if (isSpin){ return tryLockForSpin(key, value, expireTime,spinTimeOut); }else{ try { log.debug("尝试获取锁,当前线程ID{}", Thread.currentThread().getId()); boolean ret = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS); if (ret) { log.debug("获取锁成功,当前线程ID{}", Thread.currentThread().getId()); return true; } } catch (Exception ex) { ex.printStackTrace(); } return false; } } /** * @Description: 释放锁 * @date: 2021/11/29 * @param key * @param value */ public boolean unlock(String key, String value) { String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class); Object result = redisTemplate.execute(redisScript, Collections.singletonList(key), value); if (SUCCESS_UNLOCK.equals(result)) { log.debug("释放锁成功,当前线程ID{}", Thread.currentThread().getId()); return true; } return false; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通