지금까지 메세지 큐란 부하를 받을 수 있도록 하는 buffer역할을 하고,
이 부하를 받아 내면서도 서버 에러가 발생해도 요청을 유실하지 않을 수 있는 수단이라고 만 인지하고 있었습니다.
직접 구축해본 경험은 없지만, 유지보수를 해야할 입장이 되면서 개념 정도는 이해하고 있어야겠다는 생각에 정리해보았습니다.
메세지 큐는 비동기 통신을 위한 시스템입니다.
프로세스 또는 프로그램 간에 데이터를 교환할 때 사용하는 통신 방법 중 하나입니다.
Producer가 메세지를 큐에 넣고 Consumer가 메세지를 가져와서 처리하는 방식의 시스템입니다.
메세지 큐를 사용함으로써 시스템의 결합도를 낮추고, 확장성 및 유연성을 향상 시킬 수 있습니다.
redis pub/sub, kafka, RabbitMQ 등 다양한 메세지 큐들이 있고 상황에 따라 적절히 사용할 수 있습니다.
다만, 비동기로 처리되어도 괜찮고, 어플리케이션의 핵심 기능이 아닌 경우에 사용하는 것이 바람직합니다.
메세지 큐를 사용하는 이유는 다음과 같습니다.
제가 관리하는 시스템에서는 조회수 update 등과 같은 동작에서 메세지큐를 사용하고 있습니다.
실제로 메세지 큐를 통해 서버 장애 상황에서도 조회수 증가 등의 데이터를 잃지 않을 수 있었습니다.
또한, 트래픽에도 대비할 수 있을 것이라고 예상합니다.
Dead Letter Queue 입니다.
메세지 큐에서 consumer가 메세지를 처리하면서 실패하는 경우가 발생할 수 있습니다.
이때, 처리에 실패하면 다시 메세지 큐에 넣고 재시도 하도록 되어있습니다.
재시도를 진행하면서 일정 시도 횟수(MaxReceiveCount)이상 실패하면 DLQ로 이동하도록 할 수 있습니다.
이를 통해서 계속해서 실패하는 메세지로 인한 애플리케이션의 장애를 방지하고, 통신 오버헤드 비용을 감소합니다.
또한, DLQ에 쌓인 메세지를 통해 장애 상황을 분석하는 등 유용하게 사용할 수 있습니다.
이 장애 상황 분석이 DLQ를 사용하는 주된 목적입니다.

다양한 실패 원인이 있습니다.
올바르지 않은 요청일 수 있고, 네트워크 오류가 있을 수 있고, 메세지의 TTL이 만료될 수도 있고, consumer 애플리케이션이 메세지를 올바르게 처리하지 못하는 경우도 있습니다.
이 원인들 중에서 consumer가 처리하지 못한 경우 등은 재시도 시 성공하는 요청도 존재할 것입니다.
따라서 올바른 메세지를 재시도하여 처리할 수 있도록 적절한 재시도 횟수를 설정하고, 재시도 횟수 이상 실패한다면 적절하지 않은 요청으로 간주하여 DLQ로 이동시키는 것이 바람직합니다.
다만, 주의할 점은 순서가 보장되어야 하는 메세지 큐에서는 DLQ를 사용해서는 안됩니다.
예를 들어 티켓팅 시스템으로 살펴보겠습니다.
메세지 큐는 다양한 방식이 있지만, 티켓팅 시스템과 같이 순서가 보장되어야 하는 겨웅 FIFO 큐를 사용하면 메세지의 순서를 관리할 수 있습니다.
이때 DLQ를 사용한다면 장애가 발생한 메세지의 순서가 깨질 위험이 있습니다.
그 이유는 DLQ가 장애 메세지를 원본 큐에서 제거하기 때문입니다.
원본 메세지 큐에 있는 메세지를 제거하고, DLQ로 이동 시키기 때문에 순서가 보장되지 않습니다
1. 성공
2. 성공
3. 실패 -> DLQ이동
4. 성공 -> 3번이 DLQ로 이동하고 실행
이와 같은 상황이기에 티켓팅과 같이 순서가 중요한 시스템에서는 DLQ를 사용하지 않고, 순서를 보장할 수 있는 큐를 사용하거나, 순서를 보장하도록 시스템을 설계해야 합니다.