1.基础分布式锁实现
1.1代码如下:
@Slf4j
@Component
public class RedisDistributedLock {@Autowiredprivate StringRedisTemplate redisTemplate;private static final long DEFAULT_EXPIRE = 30000L; private static final long WAIT_INTERVAL = 100L; public boolean lock(String key, String value, long expireTime) {try {return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.MILLISECONDS));} catch (Exception e) {log.error("获取锁失败", e);return false;}}public boolean unlock(String key, String value) {try {String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +"return redis.call('del', KEYS[1]) " +"else return 0 end";DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();redisScript.setScriptText(script);redisScript.setResultType(Long.class);Long result = redisTemplate.execute(redisScript, Collections.singletonList(key), value);return result != null && result == 1L;} catch (Exception e) {log.error("释放锁失败", e);return false;}}
}
2.进阶版分布式锁(支持自动续期)
2.1代码如下
@Slf4j
@Component
public class AdvancedRedisLock {@Autowiredprivate StringRedisTemplate redisTemplate;private static final long DEFAULT_EXPIRE = 30000L;private static final long RENEWAL_INTERVAL = 10000L; private final Map<String, ScheduledFuture<?>> renewalTasks = new ConcurrentHashMap<>();@Autowiredprivate ScheduledExecutorService scheduler;public boolean lockWithRenewal(String key, String value, long expireTime) {try {boolean locked = lock(key, value, expireTime);if (locked) {scheduleRenewal(key, value, expireTime);}return locked;} catch (Exception e) {log.error("获取锁失败", e);return false;}}public boolean unlockWithRenewal(String key, String value) {try {cancelRenewal(key);return unlock(key, value);} catch (Exception e) {log.error("释放锁失败", e);return false;}}private void scheduleRenewal(String key, String value, long expireTime) {ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(() -> {try {String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +"return redis.call('pexpire', KEYS[1], ARGV[2]) " +"else return 0 end";DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();redisScript.setScriptText(script);redisScript.setResultType(Long.class);Long result = redisTemplate.execute(redisScript,Collections.singletonList(key),value, String.valueOf(expireTime));if (result == null || result != 1L) {cancelRenewal(key);}} catch (Exception e) {log.error("续期失败", e);cancelRenewal(key);}}, RENEWAL_INTERVAL / 3, RENEWAL_INTERVAL / 3, TimeUnit.MILLISECONDS);renewalTasks.put(key, future);}private void cancelRenewal(String key) {ScheduledFuture<?> future = renewalTasks.remove(key);if (future != null) {future.cancel(false);}}
}
3.使用装饰器模式实现可重入锁
3.1代码如下
@Slf4j
@Component
public class ReentrantRedisLock {private final ThreadLocal<Map<String, Integer>> locksHolder = ThreadLocal.withInitial(HashMap::new);@Autowiredprivate AdvancedRedisLock redisLock;public boolean lock(String key, String value, long expireTime) {Map<String, Integer> counts = locksHolder.get();Integer count = counts.get(key);if (count != null && count > 0) {counts.put(key, count + 1);return true;}if (redisLock.lockWithRenewal(key, value, expireTime)) {counts.put(key, 1);return true;}return false;}public boolean unlock(String key, String value) {Map<String, Integer> counts = locksHolder.get();Integer count = counts.get(key);if (count == null) {return false;}count--;if (count > 0) {counts.put(key, count);return true;}counts.remove(key);return redisLock.unlockWithRenewal(key, value);}
}
4. 使用AOP实现分布式锁注解
4.1代码如下:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DistributedLock {String key();long expireTime() default 30000L;long waitTime() default 5000L;
}@Aspect
@Component
@Slf4j
public class DistributedLockAspect {@Autowiredprivate ReentrantRedisLock redisLock;@Around("@annotation(distributedLock)")public Object around(ProceedingJoinPoint point, DistributedLock distributedLock) throws Throwable {String key = distributedLock.key();String value = UUID.randomUUID().toString();long waitTime = distributedLock.waitTime();long startTime = System.currentTimeMillis();while (!redisLock.lock(key, value, distributedLock.expireTime())) {if (System.currentTimeMillis() - startTime > waitTime) {throw new RuntimeException("获取锁超时");}Thread.sleep(100);}try {return point.proceed();} finally {redisLock.unlock(key, value);}}
}
5.使用示例
5.1代码如下
@Service
@Slf4j
public class OrderService {@Autowiredprivate ReentrantRedisLock redisLock;@DistributedLock(key = "'order:' + #orderId", expireTime = 30000)public void processOrder(String orderId) {try {log.info("Processing order: {}", orderId);Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}public void manualLockExample(String orderId) {String key = "order:" + orderId;String value = UUID.randomUUID().toString();try {if (redisLock.lock(key, value, 30000)) {log.info("Processing order: {}", orderId);} else {log.warn("Failed to acquire lock for order: {}", orderId);}} finally {redisLock.unlock(key, value);}}
}
6.配置如下
6.1代码如下
@Configuration
public class RedisLockConfig {@Beanpublic ScheduledExecutorService scheduledExecutorService() {return Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(),new ThreadFactoryBuilder().setNameFormat("redis-lock-renewal-%d").setDaemon(true).build());}
}