Kafka는 대규모 데이터 스트리밍을 처리하는 데 최적화된 분산 메시징 시스템이에요. 하지만 모든 메시지가 항상 성공적으로 처리되는 건 아니죠. 예를 들어, 데이터 포맷이 잘못되었거나 외부 서비스와의 통신 오류 등 다양한 이유로 메시지 처리에 실패할 수 있어요. 이런 실패한 메시지를 따로 관리하고 다시 처리할 수 있는 방법이 바로 Dead Letter Topic(DLT)입니다.
메시지 처리 중 오류가 발생하면 해당 메시지를 DLT로 보내 실패한 메시지를 별도로 관리하게 됩니다. 하지만 단순히 DLT에 메시지를 보낸 후에는 이 메시지를 어떻게 다시 처리할지 고민이 필요해요. 재처리 전략을 잘못 설계하면 시스템의 안정성이 떨어지거나 메시지 중복 처리 등의 문제가 발생할 수 있답니다. 그래서 오늘은 두 가지 DLT Replay 전략을 소개하고, 어떤 상황에서 어떤 전략이 더 적합한지 알아보려고 해요.
오늘은 두 가지 DLT Replay 전략을 살펴볼게요:
이 첫 번째 전략은 DLT에 저장된 메시지를 별도의 Retry Topic으로 전송하여 재처리하는 방법이에요. 이 방법의 가장 큰 장점은 기존의 메시지 처리 흐름을 방해하지 않고 실패한 메시지만 따로 처리할 수 있다는 점이에요.
import org.springframework.kafka.core.KafkaTemplate
import org.springframework.kafka.annotation.KafkaListener
import org.springframework.stereotype.Service
import org.apache.kafka.clients.consumer.ConsumerRecord
@Service
class DltReplayService(private val kafkaTemplate: KafkaTemplate<String, String>) {
fun replayDltMessages(dltTopic: String, retryTopic: String) {
val dltMessages = readMessagesFromTopic(dltTopic)
dltMessages.forEach { message ->
kafkaTemplate.send(retryTopic, message.key, message.value)
}
}
private fun readMessagesFromTopic(topic: String): List<ConsumerRecord<String, String>> {
// DLT에서 메시지 읽기 로직 구현
// 예: KafkaConsumer를 사용하여 메시지 조회
return listOf()
}
}
@Service
class RetryConsumerService {
@KafkaListener(topics = ["retry-topic"], groupId = "retry-group")
fun listenRetryMessages(message: String) {
try {
// 메시지 처리 로직
} catch (e: Exception) {
// 실패 시 다시 DLT로 전송 또는 최대 재시도 횟수 초과 시 DLT로 이동
}
}
}
두 번째 전략은 Consumer 그룹의 Offset을 DLT 메시지가 있는 위치로 재설정하여 메시지를 다시 처리하는 방법이에요. 이 방법은 비교적 단순하게 구현할 수 있지만, 몇 가지 단점도 존재해요.
전략 | 장점 | 단점 |
---|---|---|
DLT를 Retry Topic으로 Reproduce | - Consumer 흐름 방해 없음 - 유연한 재시도 설정 - 안정성 유지 | - 추가 리소스 필요 - 시스템 복잡성 증가 |
Consumer Offset 초기화 | - 단순한 구현 - 추가 리소스 불필요 | - Consumer 중단 필요 - 데이터 중복 처리 위험 - 복구 시간 지연 |
장점
단점
오늘은 Kafka의 DLT Replay 전략에 대해 두 가지 접근법을 살펴보았어요. Retry Topic을 활용한 전략은 시스템의 가용성을 유지하면서 유연하게 재처리를 할 수 있는 장점이 있지만, 추가 리소스가 필요하고 시스템 복잡성이 조금 증가하는 단점이 있어요. 반면, Offset 초기화 전략은 구현이 단순하고 리소스를 절약할 수 있지만, Consumer를 일시 중지해야 하고 데이터 중복 처리의 위험이 있다는 단점이 있죠.
개인적으로는 대규모 시스템이나 높은 가용성이 요구되는 환경에서는 Retry Topic을 활용한 전략이 더 적합하다고 생각해요. 하지만 소규모 프로젝트나 단순한 요구사항을 가진 경우에는 Offset 초기화 전략도 충분히 유용할 수 있습니다. 여러분의 프로젝트에 맞는 전략을 선택해서 안정적이고 효율적인 Kafka 메시지 처리를 구현해보세요!