分布式锁是分布式系统中确保资源互斥访问的核心机制,而Redisson作为基于Redis的Java客户端,提供了高效且功能丰富的分布式锁实现。本文将深入剖析Redisson分布式锁的实现原理、核心机制及源码细节,并结合实际场景提供最佳实践建议。
Redisson通过Lua脚本在Redis中执行加锁与解锁操作,确保多个命令的原子性,避免因部分命令失败导致的锁状态不一致问题。核心步骤如下:
SET key value NX PX expireTime
命令实现互斥性,结合哈希结构存储线程唯一标识(UUID + ThreadID)和重入计数器。-- 加锁脚本示例
if (redis.call('exists', KEYS[1]) == 0) then
redis.call('hincrby', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]);
return nil;
end;
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then
redis.call('hincrby', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]);
return nil;
end;
return redis.call('pttl', KEYS[1]);
同一线程可多次获取锁,通过哈希结构的计数器记录重入次数。每次加锁计数器递增,解锁时递减至0才真正释放锁,避免死锁。
若未显式指定锁超时时间,Redisson启动后台线程(默认每10秒)检查锁状态并续期(默认续至30秒),防止业务未完成时锁过期。源码核心逻辑如下:
private void renewExpiration() {
ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName());
// 续期逻辑
CompletionStage<Boolean> future = renewExpirationAsync(threadId);
future.whenComplete((res, e) -> {
if (res) renewExpiration(); // 续期成功则继续调度
});
}
waitTime
),超时后取消订阅并返回失败;收到解锁消息后重新竞争锁。if (redis.call('hexists', KEYS[1], ARGV[3]) == 1) then
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);
if (counter > 0) then
redis.call('pexpire', KEYS[1], ARGV[2]);
else
redis.call('del', KEYS[1]);
redis.call('publish', KEYS[2], ARGV[1]);
end;
end;
锁类型 | 特点 | 适用场景 |
---|---|---|
可重入锁 | 支持同一线程多次加锁 | 递归调用或嵌套锁场景 |
公平锁 | 按请求顺序分配锁 | 需要公平资源分配 |
联锁(MultiLock) | 同时锁定多个资源 | 分布式事务多资源操作 |
读写锁 | 读共享,写互斥 | 读多写少的高并发场景 |
红锁(RedLock) | 多节点多数成功机制 | 高可用性要求严格的场景 |
RedissonSpinLock
支持退避策略(如指数退避),减少竞争压力。leaseTime
和waitTime
,避免资源长期占用或线程阻塞。RLock lock = redisson.getLock("product_lock_" + productId);
try {
lock.lock();
int stock = productService.getStock(productId);
if (stock > 0) productService.reduceStock(productId);
} finally {
if (lock.isHeldByCurrentThread()) lock.unlock();
}
RReadWriteLock rwLock = redisson.getReadWriteLock("cache_lock");
RLock readLock = rwLock.readLock();
try {
readLock.lock();
String data = cacheService.get("key");
if (data == null) {
RLock writeLock = rwLock.writeLock();
try {
writeLock.lock();
data = dbService.loadFromDB("key");
cacheService.put("key", data);
} finally { writeLock.unlock(); }
}
} finally { readLock.unlock(); }
RLock lockA = redisson.getLock("account_lock_1");
RLock lockB = redisson.getLock("account_lock_2");
RedissonMultiLock multiLock = new RedissonMultiLock(lockA, lockB);
try {
multiLock.lock();
accountService.transfer(1, 2, 100);
} finally { multiLock.unlock(); }
finally
块中释放锁,并处理异常场景。Redisson通过Lua脚本原子操作、可重入设计及看门狗机制,实现了高可靠的分布式锁。开发者可根据业务需求选择合适的锁类型,并结合超时控制、读写锁优化等手段提升系统性能。理解其源码逻辑(如tryLockInnerAsync
和unlockInnerAsync
)有助于更灵活地应对复杂并发场景。