에그코드 기술 이야기 · 데이터베이스 Lock 시리즈 ④
안녕하세요, 에그코드입니다.
저희는 자체 서비스를 직접 운영하며 웹·SaaS·MVP를 만드는 개발사입니다.
3편에서 분산 락은 "락을 못 잡으면 풀릴 때까지 기다린다"고 했습니다. 그런데 그 "기다린다"를 어떻게 구현할까요?
가장 단순한 첫 방식이 스핀락(Spin Lock)입니다. 이번 4편은 Redis 클라이언트 Lettuce로 스핀락을 만들 때 챙길 점을 정리합니다.

스핀락이란 무엇인가
스핀락은 락을 못 잡으면 잠깐 쉬었다가 다시 시도하는 방식입니다. 성공할 때까지 이 재시도를 빙빙 돕니다. 그래서 "스핀(spin)"이죠.
잠긴 문의 손잡이를, 열릴 때까지 계속 흔들어보는 것과 비슷합니다.
Lettuce로는 어떻게 구현할까
Lettuce는 Redis 명령을 그대로 보내는 저수준 클라이언트라, 락 기능이 따로 없습니다. 그래서 스핀락을 직접 짜야 합니다.
방식은 단순합니다. 3편의 SET 키 값 NX PX를 반복 호출합니다. 성공하면 통과, 실패하면 잠깐 쉬었다가(sleep) 다시 시도합니다.
이 sleep을 빼면 쉴 틈 없이 재시도만 돌려 CPU를 크게 낭비합니다.

왜 조심해야 할까 — busy waiting
문제는 이 재시도가 계속 Redis에 물어본다는 점입니다. "풀렸어? 아직? 풀렸어?"를 쉼 없이 반복하는 걸 바쁜 대기(busy waiting)라고 합니다.
서버 한 대면 괜찮지만, 여러 서버가 동시에 이러면 Redis에 요청이 폭주합니다. 락 하나 기다리자고 Redis가 힘들어지는 거죠.

그래서 꼭 챙길 것
스핀락을 쓸 땐 세 가지를 반드시 넣어야 합니다.
| 꼭 챙길 것 | 왜 필요한가 |
|---|---|
| 최대 재시도 · 타임아웃 | 무한정 기다리지 않게 상한 → 지연·폭주 방지 |
| TTL (자동 만료) | 락 쥔 서버가 죽어도 저절로 풀리게 → 데드락 방지 |
| sleep 간격 | 짧으면 Redis 부하, 길면 응답 지연 → 균형점 |
이 셋만 제대로 잡아도 스핀락은 작은 서비스에서 충분히 안전하게 쓸 수 있습니다.

정리하며
스핀락은 가장 단순한 분산 락 대기 방식이지만, 공짜는 아닙니다. 바쁜 대기 탓에 재시도가 몰리면 Redis가 부담을 받습니다.
그래서 트래픽이 큰 서비스라면 "매번 물어보지 말고, 풀리면 알려달라"는 방식이 더 낫습니다. 그게 다음 편에서 다룰 Redisson pub/sub입니다.
저희 에그코드는 자체 서비스를 운영하며, 트래픽과 상황에 맞게 이런 락 방식을 골라 정합성 문제가 없도록 합니다.

다음 편 예고 — 5편 «Redisson pub/sub». 계속 물어보지 않고, 풀렸을 때만 깨어나는 방법은?
함께 읽어보세요 — 데드락과 라이브락, 동시성 함정 2가지 · 비관적 락 — 먼저 잠그고 시작하는 방식 · 에그코드 웹 개발 서비스
에그코드는 자체 서비스를 운영하며 웹·SaaS·MVP를 만듭니다. 트래픽과 상황에 맞는 락 방식을 함께 고릅니다.
동시성·데이터 정합성이 걱정된다면 문의하기