[Backend] Redisson Pub/Sub 기반 분산 락
동시성 문제(Concurrency Issue), 그리고 분산 락(Distributed Lock)
동일한 리소스에 여러 쓰레드가 동시에 접근하면 '동시성 문제'가 발생한다.'동시성 문제'란 예를 들어 하나의 쓰레드가 리소스를 수정하던 상황에서 다른 쓰레드가 수정 전의 리소스를 조회함으로서 서로 다른 리소스를 얻어가는 문제를 말한다.이러한 문제를 해결하는 데에는 여러 해결책이 있는데 그중 하나로 Java에서 사용되는 Redis 클라이언트인 Redisson를 사용하는 분산 락 방법에 대해 알아보겠다.
Lettuce 기반 스핀 락(Spin Lock)?
Spring Boot 2.0부터는 Netty 기반의 Lettuce가 Redis 기본 클라이언트로 사용됬다. Lettuce를 이용한 락 구현 시, 락을 획득하지 못한 경우 반복적으로 Redis에 요청을 보내는 방식(일명 스핀 락 방식)을 개발자가 구현하는 경우가 많았다. 이러한 방식은 Redis에 지속적인 부하를 줄 수 있다. 이를 완화하기 위해 락 획득 재시도 시간을 늘릴 경우, 락을 이미 획득할 수 있는 상황에서도 대기 시간이 길어지는 문제가 발생할 수 있다.
Pub/Sub 기반 분산 락
Pub/Sub이란 "Publication/Subscription"의 줄임말로, 발행/구독 모델을 의미한다. 스핀 락의 경우 락을 획득하기 위해 Redis에 지속적으로 요청을 보내는 방식을 사용하지만, Pub/Sub 기반 분산 락에서는 이러한 방식과 달리 각 스레드가 락을 구독(Sub)하고, 락을 획득할 수 있는 상황이 되면 Redis가 해당 스레드에 알림을 발행(Pub)한다. 이를 통해 반복적인 요청으로 Redis에 부하를 주는 문제를 해결할 수 있다. 구체적으로, Redisson은 락을 해제할 때 Pub/Sub 채널을 사용하여 락 획득을 대기 중인 스레드에 알림을 발행한다. 알림을 받은 스레드는 즉시 락을 획득할 수 있으며, 이를 통해 효율적으로 락 관리가 이루어진다. 이 메커니즘은 Redis의 Pub/Sub 모델을 활용하여 락 점유와 해제를 효율적으로 제어하는 특징이 있다.
한계점
Redisson Pub/Sub 분산 락을 포함하여 모든 외부 락 서버를 이용하는 락 방식의 공통적인 문제이지만 네트워크 지연에 굉장히 취약하다.실제로 로직이 매우 효율적이더라도 락 획득,해제 과정에서 Redis 서버와의 연결에 문제가 발생하면 장시간 대기가 발생할 수도 있다.
또한, Redis Cluster등을 사용하지 않는다면 Redis 서버 그 자체로 SPOF(Single Point of Failure; 단일 장애 지점)이 되어 심각한 장애가 될 수 있다.
어디에서 사용할까
모든 기술이 그러하지만 redisson Pub/Sub 분산 락도 모든 곳에 필요하지는 않다.오히려 부적절한 기술 적용은 개발자의 생산성을 낮추기도 하고 프로그램의 성능을 낮출수도 있다.데이터 일관성이 중요하고 복잡한 분산 환경,예를 들어 결제 시스템과 같은 곳에서 사용하고 그렇지 않다면 낙관적 락(Opimistic Lock)과 같은 다른 대안도 충분히 고민해봐야 할 것이다.