Distributed Lock이란?
여러 대의 서버가 동시에 같은 자원에 접근할 때, 특정 시점에는 오직 하나의 프로세스만 해당 자원을 처리하도록 제어하는 기법을 Distributed Lock(분산 락)이라고 합니다. 한 대의 서버 안에서는 자바의 synchronized나 뮤텍스 같은 로컬 락으로 충분하지만, 서버가 여러 대로 늘어나면 각 서버는 서로 다른 메모리 공간을 사용하기 때문에 로컬 락으로는 충돌을 막을 수 없습니다. 이때 여러 서버가 함께 참조할 수 있는 ‘공용 저장소'(Redis, ZooKeeper, DB 등)에 락 정보를 기록해 조율하는 방식이 분산 락입니다.
동작 원리와 예시
가장 널리 쓰이는 방식은 Redis를 이용한 락입니다. 원리는 간단합니다. 특정 키가 ‘존재하지 않을 때만’ 값을 저장하는 명령(예: ‘SET key value NX EX 10’)을 사용해, 이미 누군가 락을 잡고 있으면 다른 프로세스는 저장에 실패하고, 성공한 프로세스만 자원에 접근할 수 있게 합니다.
비유하자면 회의실 예약 시스템과 비슷합니다. 회의실 문 앞에 ‘예약중’ 팻말이 걸려 있으면 다른 사람은 들어가지 못하고 기다리거나 포기해야 합니다. 팻말을 거는 행위가 락을 획득하는 것이고, 회의가 끝난 뒤 팻말을 치우는 것이 락을 해제하는 것입니다. 만약 회의가 끝났는데 누군가 팻말을 치우지 않고 사라지면 방은 영원히 비어있는데도 아무도 못 들어가는 문제가 생기는데, 이를 방지하기 위해 락에는 보통 만료 시간(TTL)을 걸어둡니다. 서버가 다운되더라도 일정 시간이 지나면 팻말이 자동으로 사라지도록 하는 것입니다.
실무에서 왜 필요한가
실무에서는 재고 차감, 결제 중복 처리 방지, 스케줄러의 중복 실행 방지 등에 분산 락이 자주 사용됩니다. 예를 들어 여러 서버 인스턴스가 동시에 같은 배치 작업을 실행하면 데이터가 중복 처리될 수 있는데, 분산 락을 걸어두면 오직 하나의 인스턴스만 작업을 수행하도록 강제할 수 있습니다.
- Redis 기반: 속도가 빠르고 구현이 간단해 대부분의 서비스에서 채택
- ZooKeeper/etcd 기반: 강한 일관성과 장애 감지가 중요한 시스템에서 사용
- DB 기반: 별도 인프라 추가 없이 기존 DB로 처리 가능하지만 성능 이슈 존재
분산 락은 만능 해결책은 아닙니다. 락을 잡은 서버가 응답 없이 오래 걸리면 TTL이 만료되어 다른 서버가 동시에 자원에 접근하는 문제가 생길 수 있고, 네트워크 지연으로 락 상태 판단이 어긋날 수도 있습니다. 그래서 락의 만료 시간 설정, 재시도 정책, 락 소유자 검증 로직을 신중하게 설계하는 것이 중요합니다.