redis实现分布式锁
2026/5/13 14:23:35 网站建设 项目流程

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询