Redis 분산 락

한 줄 정의

Redis 분산 락은 여러 서버 인스턴스가 동시에 같은 작업을 처리하지 않도록 Redis key를 원자적으로 선점하는 방식이다.

실무에서 왜 문제 되는가

  • 서버가 여러 대이면 JVM의 synchronized나 로컬 락만으로는 중복 실행을 막을 수 없다.
  • 락 만료 시간이 작업 시간보다 짧으면 락을 잡은 작업이 끝나기 전에 다른 요청이 락을 얻을 수 있다.
  • 락 해제 시 소유자 확인을 하지 않으면 다른 요청의 락을 지울 수 있다.
  • 분산 락은 동시 실행 가능성을 줄이는 도구이지, DB 정합성을 완전히 대체하지 않는다.

동작 원리

  1. 작업 시작 전 SET key value NX PX milliseconds로 lock key를 저장한다.
  2. 저장에 성공한 요청만 작업을 수행한다.
  3. lock key에는 TTL과 소유자 token을 함께 둔다.
  4. 작업이 끝나면 Lua script 등으로 token 확인과 key 삭제를 원자적으로 수행한다.
  5. 작업 중 서버가 죽으면 TTL 이후 lock key가 만료된다.

실무 판단 기준

상황분산 락 판단이유
중복 실행되어도 재시도 가능적합락 실패 시 나중에 다시 처리할 수 있다
결제 승인처럼 정합성이 매우 중요보조 수단DB 제약, 멱등키, 상태 체크가 함께 필요하다
작업 시간이 예측 가능적합TTL을 합리적으로 정할 수 있다
작업 시간이 길고 변동이 큼주의TTL 연장, 작업 분할, 큐 기반 처리 검토가 필요하다
단일 DB row 갱신 경쟁DB 락 우선 검토데이터 정합성은 DB가 더 직접적으로 보장한다
Redis 장애 중에도 반드시 한 번만 실행부적합락 저장소 장애와 네트워크 분리를 완전히 제거할 수 없다

자주 나는 실수

  • SETNX 후 별도 명령으로 EXPIRE를 걸어 원자성이 깨진다.
  • 락 value 없이 key만 삭제해서 다른 요청의 락을 지운다.
  • token 확인과 삭제를 별도 명령으로 실행해 race condition을 만든다.
  • 작업 시간보다 짧은 TTL을 설정한다.
  • 락 획득 실패를 성공처럼 처리한다.
  • 분산 락만 믿고 DB unique constraint나 상태 검증을 제거한다.
  • Redis 장애나 failover 중 락의 안전성이 어떻게 달라지는지 검토하지 않는다.

확인 방법

  • 테스트: 동시에 같은 요청을 여러 번 보내 중복 처리가 없는지 확인한다.
  • 장애 실험: 락 획득 후 프로세스를 종료해 TTL 이후 복구되는지 확인한다.
  • 로그: lock acquire success/fail, lock wait time, lock release fail을 남긴다.
  • 메트릭: 락 획득 실패율, 대기 시간, 작업 수행 시간, TTL 초과 비율을 본다.

핵심 요약

Redis 분산 락은 여러 애플리케이션 인스턴스가 같은 작업을 동시에 실행하지 않게 줄여주는 도구다. 락 획득은 NX와 TTL을 원자적으로 설정해야 하고, 해제는 소유자 token 확인과 삭제를 원자적으로 수행해야 한다. TTL은 서버 장애 시 락이 영원히 남지 않게 하지만, 작업 시간보다 짧으면 중복 실행을 만들 수 있다. 중요한 비즈니스 정합성은 분산 락만으로 보장하지 말고 DB 제약, 멱등키, 상태 전이 조건과 함께 설계한다.

꼬리 질문

  • SETNXEXPIRE를 따로 실행하면 어떤 문제가 생기는가?
  • 락 TTL보다 작업 시간이 길어지면 어떤 일이 생기는가?
  • 분산 락과 DB unique constraint는 어떤 차이가 있는가?
  • 락 해제 시 소유자 token을 확인해야 하는 이유는 무엇인가?
  • 분산 락만으로 중복 처리를 완전히 막을 수 있는가?
  • Redis failover 중에는 분산 락의 안전성을 어떻게 판단할 것인가?

관련 문서