当前位置: 首页 > news >正文

redis实现分布式锁

redis实现分布式锁

@ComponentpublicclassRedisDistributedLock{@AutowiredprivateRedisTemplate<String,String>redisTemplate;privatestaticfinalStringLOCK_PREFIX="lock:";privatestaticfinallongDEFAULT_EXPIRE=30_000;// 默认30秒// 加锁(带UUID防误删)publicStringtryLock(StringlockKey,longexpire){StringrequestId=UUID.randomUUID().toString();booleanresult=redisTemplate.opsForValue().setIfAbsent(LOCK_PREFIX+lockKey,requestId,expire,TimeUnit.MILLISECONDS);returnresult?requestId:null;}// 解锁(验证锁持有者身份后删除)publicbooleanunlock(StringlockKey,StringrequestId){Stringkey=LOCK_PREFIX+lockKey;StringcurrentRequestId=redisTemplate.opsForValue().get(key);if(requestId.equals(currentRequestId)){returnredisTemplate.delete(key);}returnfalse;}}

lua脚本实现方式

publicclassRedisDistributedLock{privateRedisTemplate<String,Object>redisTemplate;privateStringlockKey;privateStringlockValue;privateintexpireTime;// 获取锁的Lua脚本privatestaticfinalStringACQUIRE_LOCK_SCRIPT="if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then "+"redis.call('expire', KEYS[1], tonumber(ARGV[2])) "+"return 1 "+"else "+"return 0 "+"end";// 释放锁的Lua脚本privatestaticfinalStringRELEASE_LOCK_SCRIPT="if redis.call('get', KEYS[1]) == ARGV[1] then "+"return redis.call('del', KEYS[1]) "+"else "+"return 0 "+"end";publicRedisDistributedLock(RedisTemplate<String,Object>redisTemplate,StringlockKey,intexpireTime){this.redisTemplate=redisTemplate;this.lockKey=lockKey;this.expireTime=expireTime;this.lockValue=UUID.randomUUID().toString();}/** * 尝试获取分布式锁 * @return 是否获取成功 */publicbooleantryLock(){RedisScript<Long>script=newDefaultRedisScript<>(ACQUIRE_LOCK_SCRIPT,Long.class);Longresult=redisTemplate.execute(script,Collections.singletonList(lockKey),lockValue,String.valueOf(expireTime));returnresult!=null&&result==1;}/** * 释放分布式锁 * @return 是否释放成功 */publicbooleanreleaseLock(){RedisScript<Long>script=newDefaultRedisScript<>(RELEASE_LOCK_SCRIPT,Long.class);Longresult=redisTemplate.execute(script,Collections.singletonList(lockKey),lockValue);returnresult!=null&&result==1;}/** * 带超时的获取锁方法 * @param timeout 超时时间(毫秒) * @return 是否获取成功 */publicbooleantryLock(longtimeout){longstartTime=System.currentTimeMillis();do{if(tryLock()){returntrue;}try{Thread.sleep(100);// 短暂休眠避免过度竞争}catch(InterruptedExceptione){Thread.currentThread().interrupt();returnfalse;}}while(System.currentTimeMillis()-startTime<timeout);returnfalse;}}

代码说明:

  1. 使用RedisTemplate的setIfAbsent方法实现原子加锁操作
  2. 通过UUID生成唯一请求ID,防止误删其他客户端的锁
  3. 解锁时通过Lua脚本验证锁持有者身份,确保原子性
  4. 支持自定义过期时间,防止死锁
  5. 依赖Spring框架,需配置RedisTemplate Bean
http://www.cnnetsun.cn/news/1543.html

相关文章:

  • 【踩坑记录】pandas.to_sql 报 “‘Engine‘ object has no attribute ‘cursor‘”,最后竟然是环境问题
  • 汇编:外设连接与中断
  • 为何要配光伏储能协调控制服务器?核心价值与应用必要性
  • 优选算法-004 盛最多水的容器
  • 一个构建指定坐标轴在默认点(0,0)的构造方法《python语言程序设计》2018版--第8章17题第2部分
  • 知识点总结
  • 初级电气工程师考试题2
  • 【强化学习】第二章:老虎机问题、ε-greedy算法、指数移动平均
  • Oracle数据库内存管理实操指南:PGA与SGA优化实战
  • 1分钟搭建 Redis三主三从集群!附完整自动化脚本(直接复制可用)
  • 在线教程丨30毫秒处理100个检测对象,SAM 3实现可提示概念分割,性能提升2倍
  • 基于web的酒品商城购物系统的设计与实现-计算机毕业设计源码31522
  • 软件代码去个性化是智能制造落地的有效途径
  • 如何了解腾讯云国际站代理商FL有什么跨境优势呢?
  • 开发日志-正点原子RK3568运行Qt项目
  • 萨拉赫如何用一次采访,毁掉自己在利物浦的八年传奇?
  • 18场造14球仍遭弃!巴萨为何对拉什福德关上大门?
  • 如何设计安全的 Web API 访问
  • 算法竞赛备考冲刺必刷题(C++) | AcWing 1169 糖果
  • 算法竞赛备考冲刺必刷题(C++) | 洛谷 P5960 差分约束
  • 工业智能体的五级跃迁:从对话到执行的智能化革命
  • C语言实现isalpha函数功能(附带源码)
  • C语言实现多种方法求解定积分(附带源码)
  • C语言实现骑士旅游算法(附带源码)
  • C语言实现toupper函数功能(附带源码)
  • C语言实现isdigit函数功能(附带源码)
  • C语言实现维吉尼亚密码加解密算法(附带源码)
  • C语言实现仿射变换加解密算法(附带源码)
  • C语言实现文件分割(附带源码)
  • C语言实现辗转相除法(附带源码)