AI

[동시성] 락 대기가 클라이언트 타임아웃보다 길면 안 되는 이유

jykim23 2026. 8. 2. 19:50
반응형

동시성 락 대기 클라이언트 타임아웃 fail-fast asyncio shield release 버스트

부제: 락 대기·해제가 요청 하나를 줄줄이 막던 버스트를 잡은 이야기

사용자 정보를 갱신할 때 락을 건다.
같은 사용자를 두 요청이 동시에 고치지 못하게 막으려는 것이다.
평소엔 잘 돌았는데, 어느 시간대에 요청들이 줄줄이 60초씩 멈추는 일이 몰려서 났다.

줄줄이 60초씩 멈췄다

버스트를 뜯어보니 세 가지가 겹쳐 있었다.

첫째, 락 대기 시간이 하필 클라이언트 타임아웃과 정확히 같았다(둘 다 60초).
그래서 새 요청이 락을 기다리는 60초 사이에 클라이언트가 먼저 끊겼다.
락이 풀리는 순간이 하필 클라이언트가 막 떠난 직후였다.

둘째, 락 해제를 취소로부터 보호하지 않았다.
요청이 취소되면 그 취소가 전파되면서, 락을 푸는 코드가 절반만 실행됐다.
그러면 락이 제대로 안 풀리고, 만료 시간(60초)이 될 때까지 남았다.

셋째, 이렇게 안 풀리고 남은 락이 뒤따르는 요청들을 줄줄이 60초씩 대기시켰다.
새는 락 하나가 버스트를 만든 것이다.

대기는 클라이언트보다 짧게, 해제는 취소로부터 보호

세 군데를 고쳤다.

락을 붙잡는 시간을 60초에서 30초로 줄였다.
실제 작업은 몇 초면 끝나니 넉넉하고, 혹시 락이 새더라도 남는 시간이 절반으로 준다.

락을 기다리는 시간은 60초에서 10초로 줄였다(fail-fast).
클라이언트가 끊기기 한참 전에 빠르게 포기하고, 뒤에서 도는 복구 작업이 다음 사이클에 다시 시도하게 했다.
괜히 오래 붙들고 있다 클라이언트만 잃는 것보다 낫다.

락 해제는 취소로부터 감쌌다.
요청이 취소된 상태로 정리 구간에 들어와도, 해제 코드는 끝까지 완주하게 했다.
그래야 락이 새지 않는다.

정리

  • 락 대기(60초)가 클라이언트 타임아웃(60초)과 같아, 기다리다 클라이언트가 먼저 끊겼다
  • 해제가 취소 전파로 절반만 실행돼 락이 만료까지 남았다
  • 새는 락이 뒤 요청들을 줄줄이 대기시켜 버스트가 났다
  • 락 대기는 클라이언트 타임아웃보다 짧게(fail-fast), 해제는 취소로부터 보호(shield), 보유 시간도 단축

락을 기다리는 시간은 반드시 클라이언트가 버티는 시간보다 짧아야 한다.
그리고 정리 코드는 취소로부터 지켜야 한다.
안 그러면 새는 락 하나가 요청을 줄줄이 무너뜨린다.

반응형