1. Lettuce를 이용한 직접 구현
특징:
- Lettuce는 Redis와 비동기로 통신할 수 있는 자바 클라이언트 입니다.
- 직접 분산 락을 구현하려면 **SETNX** 와 **EXPIRE** 명령어를 활용해야 합니다.
public boolean acquireLock(String lockKey, String requestId, long expireTime) {
String result = redisTemplate.execute((RedisCallback<String>) connection -> {
return connection.set(
lockKey.getBytes(),
requestId.getBytes(),
Expiration.from(expireTime, TimeUnit.MILLISECONDS),
RedisStringCommands.SetOption.SET_IF_ABSENT
);
});
return "OK".equals(result);
}
public boolean releaseLock(String lockKey, String requestId) {
String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
" return redis.call('del', KEYS[1]) " +
"else " +
" return 0 " +
"end";
Long result = redisTemplate.execute((RedisCallback<Long>) connection -> {
return connection.eval(
luaScript.getBytes(),
ReturnType.INTEGER,
1,
lockKey.getBytes(),
requestId.getBytes()
);
});
return result != null && result > 0;
}
--- // 또는 단일 환경에서 아래의 메서드도 가능
public boolean releaseLock(String lockKey, String requestId) {
String currentValue = redisTemplate.opsForValue().get(lockKey);
if (requestId.equals(currentValue)) {
redisTemplate.delete(lockKey);
return true;
}
return false;
}
루아 스크립트를 사용하지 않고도 releaseLock메서드를 구현할 수 있습니다. 하지만 이 경우
get명령어와del명령어가두 번의 Redis 명령으로 분리되어 실행되기 때문에**원자성(atomicity)**이 보장되지 않습니다.
루아 스크립트를 사용하는 이유는 두 명령을 하나의 트랜잭션으로 처리하여 데이터 일관성을 보장하기 위해서입니다.
장점:
- 가볍다: 최소한의 Redis 명령어로 구성되어 있어 효율적입니다.
- 유연성: 요구사항에 맞게 커스터마이징이 가능합니다.
- 학습 기회: Redis 분산 락의 동작 원리를 직접 이해할 수 있습니다.
단점:
- 재시도 로직 미구현: 락 획득 실패 시 재시도 로직을 직접 작성해야 합니다.
- 신뢰성: 네트워크 분할이나 Redis 장애 시 잠금의 신뢰성을 보장하기 어렵습니다.
- RedLock 알고리즘 미지원: 단일 Redis 노드 환경에서만 적합하며, 클러스터 환경에서는 추가적인 구현이 필요합니다.
2. Redisson을 이용한 RLock
특징:
- Redisson은 Redis 기반의 고수준 Java 클라이언트입니다.
- RLock은 Redisson에서 제공하는 분산 락으로, 락의 신뢰성을 보장하는 여러 메커니즘을 제공합니다.
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379");
RedissonClient redisson = Redisson.create(config);
RLock lock = redisson.getLock("lockKey");
try {
if (lock.tryLock(10, 5, TimeUnit.SECONDS)) { // 10초 동안 락을 시도, 5초간 점유
// critical section
}
} finally {
lock.unlock();
}
장점:
- 편리성: 락 획득, 해제, 재시도 로직 등을 Redisson이 자동으로 처리합니다.
- 신뢰성: Watchdog(감시 타이머)을 통해 TTL 연장 기능을 제공하여, 프로세스가 다운되어도 락이 영구적으로 점유되지 않도록 합니다.
- RedLock 알고리즘 지원: 다중 Redis 노드 환경에서도 사용 가능하며 신뢰성이 높습니다.
- 기능 풍부: 공정 락, 읽기-쓰기 락, 블로킹 락 등 다양한 락 기능을 제공합니다.
단점:
- 무거움: 추가적인 라이브러리 의존성과 상대적으로 높은 메모리 사용량이 있습니다.
- 복잡성 숨김: 내부 동작을 추적하거나 디버깅하기 어려울 수 있습니다.
- 성능: Lettuce 기반 직접 구현보다 약간의 성능 오버헤드가 발생할 수 있습니다.
'기타' 카테고리의 다른 글
Redis 자료구조 이해하기 (0) | 2025.01.07 |
---|---|
회고 - Jmeter 를 활용한 성능 테스트 (0) | 2025.01.01 |
로컬 캐시(Local Cache) vs 글로벌 캐시(Global Cache) (0) | 2024.12.29 |
캐시란 무엇일까? (0) | 2024.12.23 |
동기 vs 비동기 (feat. Blocking vs Non-blocking) (2) | 2024.12.23 |