SQL Maxis: RabbitMQ를 Postgres Queue로 교체한 이유
(prequel.co)- RabbitMQ를 걷어내고 PostgresDB에 SQL을 이용한 큐로 교체
- 교체에는 반나절 정도 걸렸고, 소스는 580라인 줄어듬
- 훨씬 중요한 것은 안정성과 복원성(Resiliency)가 크게 향상 되었다는 것
- RabbitMQ 같은 큐 시스템의 문제에 대한 얘기가 아니고, 단순하게 유지하기 위한 노력의 일환
- 이 글을 작성한 Prequel은 대규모 데이터 파이프라인으로 B2B SaaS회사들이 고객의 DB와 동기화 하는 것을 도와주는 제품
- RabbitMQ + AQMP + Helm + GoLang 래퍼로 구성했는데, 한동안 잘 동작했지만 문제가 나타나기 시작
- 메시지 전송이 너무 오래 지연되면서 메시지가 취소되는 일이 발생
- 컨슈머가 메시지를 프리페칭 하면서, 현재 메시지를 완료할 때까지 다음 메시지를 잡아놓는 상황이 발생
- 이 프리페치를 0으로하면 무한대가 되어서 프리페치를 비활성화 하는게 불가능
- 메시지를 받아서 처리하는 작업들이 보통 장기작업(데이터 전송)이어서 생기는 문제
- 무슨 일이 일어나는지 정확히 알게 되었지만, 즉시 고칠 방법이 없었음. 프로덕션 고객에게 문제가 발생한 거라 기다리는게 불가능
- 그래서 Postgres에서 간단한 1개의 테이블을 이용해서 읽고 쓰는 방식으로 동작
- 읽기/쓰기 Row-Level Lock을 이용해서 하나의 컨슈머만 작업을 읽도록 보장
- 터무니 없이 간단하지만 완벽하게 작동중
- 애플리케이션 상태가 RabbitMQ와 Postgres로 분할되지 않고 하나에 통합된 장점
저도 mysql 에서 row level lock 으로 큐를 직접 구현해서 수년간 제품에서 잘 동작하고 있는데요,
단순히 여러개의 워커에 큐와 유사한 기능을 제공하면서 큐 내에서 대기/진행중/실패(완료면 삭제) 상태를 포함한 payload 를 같이 저장할 수 있는 것을 원했습니다.
본문에서 짧은 시간에 rabbitmq에서 디비로 전환시킨 것을 보면 굳이 별도의 전문 큐 서비스의 범용성이나 다양한 기능과 설정 가능성이 필요하지 않았기 때문이 아닌가 싶습니다.
수동 ACK 전송과 DB 트랜잭션 사이에 밀리면서 문제가 생긴 모양인데,
이걸 엔지니어링이 아니라 RabbitMQ를 걷어내는 걸로 한게 재밌네요.
RabbitMQ는 죄가 없을텐데...