백엔드 면접 용어 사전
캐시·Redisdistributed lock

분산 락

여러 인스턴스 간 임계 구역을 지키는 락. Redis로 구현할 때 소유자 검증과 만료 처리가 필수다.

여러 서버(프로세스)가 하나의 자원을 동시에 건드리지 못하게 막는 락. 단일 프로세스의 뮤텍스로는 해결되지 않는다 — 서버가 여러 대면 각자의 메모리에 각자의 락이 있을 뿐이기 때문이다.

Redis로 만드는 최소 형태

SET lock:order:123 <랜덤토큰> NX PX 3000

옵션의미없으면
NX키가 없을 때만 성공남의 락을 덮어씀
PX 30003초 후 자동 만료락을 쥔 채 죽으면 영원히 잠김
<랜덤토큰>내가 건 락인지 식별남의 락을 푸는 사고

해제는 반드시 원자적으로

-- 토큰이 내 것일 때만 삭제 (Lua 스크립트로 원자 실행)
if redis.call("get", KEYS[1]) == ARGV[1] then
  return redis.call("del", KEYS[1])
else
  return 0
end

왜 확인이 필요한가

  1. A가 락 획득 (만료 3초)
  2. A의 작업이 4초 걸림 → 3초에 락 자동 만료
  3. B가 락 획득
  4. A가 작업을 마치고 DEL → B의 락을 지워 버림
  • 5. C도 락 획득 → B와 C가 동시에 임계 구역 — ← 락이 무너짐

토큰을 확인하면 4번에서 A는 "내 토큰이 아니네" 하고 지우지 않는다.

그래도 남는 문제 — 2번 자체

토큰 확인은 남의 락을 푸는 것만 막는다. A가 만료된 줄 모르고 계속 작업하는 상황은 그대로다. 그래서

  • 작업 시간을 만료 시간보다 확실히 짧게 잡거나
  • watchdog으로 작업 중 주기적으로 만료를 연장하거나(Redisson이 이렇게 한다)
  • 애초에 락에 정합성을 걸지 않는다

마지막 항목이 가장 중요하다

Redis 단일 노드가 죽으면 락 정보가 사라진다. Redlock(여러 노드 과반 획득)이 제안됐지만 안전성 논쟁이 있다(마틴 클레프만의 비판).

그래서 실무의 정답은 이렇다.

락은 성능 최적화(중복 작업 방지)로 쓰고, 최종 정합성은 DB가 보장하게 한다.

-- 락이 뚫려도 이건 뚫리지 않는다
UPDATE stock SET qty = qty - 1 WHERE id = 1 AND qty >= 1;
-- 또는 유니크 제약으로 중복 삽입 차단

락이 실패해도 데이터가 깨지지 않는 설계를 먼저 만들고, 락은 그 위에 얹는다.

면접 답변 골격

"Redis 분산 락은 NX·PX·토큰 검증이 기본이고, 해제는 Lua로 원자화합니다. 다만 락만으로 정합성을 보장하지 않고 DB의 조건부 갱신이나 유니크 제약을 최종 방어선으로 둡니다."

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 캐싱·Redis — 전략·eviction·스탬피드·자료구조