# 분산 환경에서 레디스를 활용한 잠금
- SET NX 명령어를 사용하여 분산 잠금 구현 가능
- SET NX 옵션은 특정 Key에 해당하는 값이 존재하지 않을 때만 값 추가 가능
- SET 명령어를 성공적으로 수행한 서버는 잠금을 획득
- 작업이 끝난 이후 Key에 해당하는 값을 제거
# 잠금이 유실되는 상황
- 레플리케이션 상황에서 마스터 노드가 존재하고 레플리카 노드에 주기적으로 데이터를 복제하는 구성
- 특정 서버가 잠금을 획득하고 작업을 수행하는 도중에 마스터 노드에 장애가 발생하여 레플리가 노드가 마스터 노드로 승격된 경우(failover)
- 마스터 노드가 가지고 있던 잠금 데이터들을 레플리카 노드가 가지고 있지 않은 상태라면 잠금이 유실됨
- 복제 지연으로 인해 분산 잠금의 상호 배제라는 특성을 읽게 됨
- RedLock 알고리즘으로 해결 가능
# RedLock 알고리즘
- 1대 이상의 레디스 노드들에 대해 과반수 이상의 노드에 잠금을 획득한다면 잠금을 획득하는 것으로 간주
- Redlock 을 위해 구성된 레디스 노드들은 같은 클러스터에 참여하거나, 복제를 하는 등 서로 연관되어 있어서는 안되며, 완전히 독립되어야 함
# RedLock 과정
- 현재 시각을 ms 단위로 가져옴
- 락 획득에 걸린 시간을 계산하기 위해 사용됨
- 클라이언트는 모든 N개의 마스터 노드로부터 순차적으로 락 획득을 시도
- 이떄, 클라이언트는 해당 키에 랜덤한 값을 저장
- 해당 랜덤 값으로 락을 획득한 클라이언트만이 해당 락을 해제할 수 있도록 보장
- 특정 레디스 노드에 락이 이미 걸려있다면, 즉시 다음 노드로 넘어감 (다른 클라이언트와 락 획득 경쟁이 발생한 상황)
- 락 설정시 타임아웃을 적용
- 클라이언트는 각 레디스 인스턴스에 락을 설정할 때, 한 노드를 너무 오래기다리지 않도록 타임아웃을 설정
- 타임아웃을 작게 설정하여 레디스 노드가 다운된 상황이라도 오래 기다리지 않고 바로 다음 노드로 넘어갈 수 있게 함
- 락 획득 성공 여부 판단
- 클라이언트는 모든 레디스 노드로부터 락 설정 시도를 마치고, 과반수 이상의 인스턴스에서 락을 획득 했는지 확인
- 락 유효 시간 계산
- 클라이언트는 락 유효 시간(Lock Validity Time)을 계산
- 클라이언트는 락 유효 시간 만큼 임계영역에서 작업을 할 수 있음
- LockValidityTime = TTL - (T2 - T1)
- TTL : 레디스 키에 설정된 TTL
- T1 : 최초 노드에서 Key가 SET 된 최악의 시각 (첫번째 노드에 통신하기 전에 얻어온 시각)
- T2 : 마지막 노드에서 Key가 SET 된 최악의 시각 (마지막 노드로부터 응답을 받은 시각)
- 락 획득 실패 시 처리
- 만약 클라이언트가 락 획득에 실패한 경우, 모든 레디스 인스턴스에서 락을 해제
# RedLock 실제 구현
- Redis 명령으로 락 획득
- 클라이언트는 아래와 같은 SET 명령을 수행하여 락을 획득
SET resource_name my_random_value NX PX 30000
- NX : 키가 존재하지 않을 때만 값을 설정
- PX : 키의 TTL을 밀리세컨드 단위로 설정
- Lua Script 를 사용하여 락 해제 락 해제 작업을 Atomic 하게 수행하기 위해, 클라이언트는 아래와 같은 Lua Script 를 실행하여 락을 해제
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
- KEYS[1] : 해제하려는 락의 Key 를 지정. 여기서는 resource_name 에 해당하는 값을 전달
- ARGV[1] : Lua Script 에서 사용할 인자의 값. 여기서는 my_random_value 에 해당하는 값을 전달
# my_random_value란?
- 랜덤한 값으로, 락을 획득한 클라이언트만이 락을 해제할 수 있도록 보장하는데 사용
- 락을 획득하지 않은 클라이언트가 임의로 락을 해제하는걸 막기 위해, 락을 설정할 때 클라이언트가 랜덤 값을 생성하고, 락 Key의 Value 로 사용
- 락을 해제할 때, 자신이 생성한 랜덤 값을 제시해서, 일치하는 경우에만 락을 해제
- 클라이언트가 락의 소유권을 증명하는 일종의 비밀번호
출처 : https://hudi.blog/redlock-algorithm/