[RabbitMQ] 메시지 유실 발생 가능 상황 및 유실 방지 방법

뿌이·2024년 9월 23일
0

RabbitMQ

목록 보기
1/2
post-thumbnail

1. 메시지 유실이 발생할 수 있는 상황

1-1. 메시지가 큐에 도달하기 전에 발생하는 장애:

메시지가 브로커에 도달하지 않았거나 전송 중 네트워크 오류가 발생할 경우 메시지가 손실될 수 있습니다.

해결방안: Publisher Confirm

Java에서 메시지를 브로커로 전송을 하는데 그 과정에서 장애가 발생할 수 있다.
보통 메시지를 보내고 메시지가 큐에 정상적으로 저장이되었는지는 확인하지 않기때문에 이를 방지할 수 있는 Publisher Confirm 이라는 기능이 rabbitMQ에 존재한다.
Publisher Confirm 개념

1-2. 큐에 저장된 메시지가 서버 장애로 손실:

큐에 저장된 메시지가 RabbitMQ 서버가 다운되거나 장애가 발생할 때 손실될 수 있습니다.

해결방안: Durable 큐 설정, Persistent Message(지속성 메시지)

하단 2-1,2-2 참고

1-3. 메시지 소비 도중 소비자가 실패:

소비자가 메시지를 가져간 후 처리를 완료하기 전에 장애가 발생하면 메시지가 손실될 수 있습니다. 이 경우 자동으로 "ack"이 설정되어 있으면, RabbitMQ는 메시지가 성공적으로 처리되었다고 간주하고 삭제할 수 있습니다.

해결방안 : Manual Acknowledgment, Dead-Letter Queue (DLQ)

하단 2-3,2-4 참고

2. 메시지 유실 방지 방법

2-1. Durable Queue(내구성 큐):

방지하는 문제: RabbitMQ 서버가 재시작될 때 큐 자체가 사라지는 문제를 방지합니다.

방지하지 못하는 문제: 메시지가 큐에 도달하기 전에 서버가 다운되면, 큐에 도착하지 못한 메시지는 유실될 수 있습니다.

큐 자체를 내구성 있게 만듦으로써 RabbitMQ가 재시작되어도 큐가 유지됩니다. 큐를 선언할 때 durable 옵션을 true로 설정합니다.

channel.queueDeclare("queueName", true, false, false, null);

2-2. Persistent Message(지속성 메시지)

방지하는 문제: RabbitMQ 서버가 재시작될 때 큐에 이미 저장된 메시지가 유실되는 것을 방지합니다.

방지하지 못하는 문제: 메시지가 큐에 도달하기 전에 또는 소비자가 가져간 후 RabbitMQ 서버가 장애를 겪으면 메시지는 여전히 유실될 수 있습니다.

메시지를 지속적으로 저장해 서버 장애에도 메시지를 유실하지 않도록 합니다. 메시지를 보낼 때 MessageProperties.PERSISTENT_TEXT_PLAIN 옵션을 사용합니다.

channel.basicPublish("", "queueName", MessageProperties.PERSISTENT_TEXT_PLAIN, messageBody);

2-3. Manual Acknowledgment(수동 확인):

방지하는 문제: 소비자가 메시지를 처리하기 전에 장애가 발생했을 때, RabbitMQ가 메시지를 삭제하지 않도록 방지합니다.

방지하지 못하는 문제: 메시지가 큐에 도달하기 전에 유실되거나, 큐 자체가 사라지면 방지할 수 없습니다.

소비자가 메시지를 처리한 후 직접 RabbitMQ에 메시지 처리가 완료되었음을 알리는 방법입니다. 이를 통해 소비자가 처리 실패 시 메시지를 다시 큐에 남겨둘 수 있습니다.

channel.basicAck(deliveryTag, false); //메시지 처리가 성공됐음을 알림
//deliveryTag: RabbitMQ가 해당 메시지를 식별하는 고유 ID로, 어떤 메시지를 ack 처리할지 
//지정하는 데 사용됩니다.
//false: 여러 메시지를 한꺼번에 처리할지 여부를 나타냅니다. false이면 해당 deliveryTag에 
//해당하는 하나의 메시지만 ack 처리됩니다.

2-4. Dead-Letter Queue (DLQ):

방지하는 문제: 소비자가 처리 실패한 메시지를 별도의 큐로 보내어 유실을 방지합니다.

방지하지 못하는 문제: DLQ로 가기 전 메시지 자체가 유실되거나, 큐나 메시지가 내구성 없으면 서버 재시작 시 유실될 수 있습니다.

소비자가 처리하지 못한 메시지를 자동으로 다른 큐에 전달하여 유실을 방지할 수 있습니다. 이를 통해 일정 시간이 지나거나 재시도 실패한 메시지를 별도로 관리할 수 있습니다.

rabbitMQ는 alk 응답이 오지 않은 메시지는 다시 큐에 넣어 메시지 재전송을 하는데 DLQ가 왜 필요해?

메시지 전송에 실패한 것은 이유가 잇는데 지속적으로 재전송을 하게되면 비효율적이기 때문이다.
따라서 최대 전송횟수를 정해두고 이를 초과하면 DLQ(전송 실패 메시지를 모아두는 큐) 에 넣는 방식이 효과적

DLQ와 재전송의 차이

3. 결론

각 방법이 해결하는 문제가 다르기 때문에, 최소한 두 가지 이상의 방법을 함께 사용하는 것이 바람직합니다.

예를 들어:

Durable QueuePersistent Message를 함께 사용하면, 서버 재시작 시 메시지와 큐 모두가 안전하게 보존됩니다.
Manual Acknowledgment와 함께 사용하면 소비자가 처리하지 않은 메시지가 안전하게 큐에 남게 됩니다.
이렇게 여러 가지 방법을 조합해서 사용하는 것이 이상적이며, 특정한 문제 상황에서도 메시지 유실을 최대한 방지할 수 있습니다.

profile
기록이 쌓이면 지식이 된다.

0개의 댓글