Files
llm-wiki/raw/official-docs/spring-kafka-non-blocking-retry-topic-ordering-loss.md

81 lines
9.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: official-doc / Spring for Apache Kafka — Non-Blocking Retry Topic Pattern (Ordering Loss)
source_type: official-doc
url: https://docs.spring.io/spring-kafka/reference/retrytopic/how-the-pattern-works.html
archive_url:
related_branches: [feature-kafka-consumer-inbox-contract]
related_projects: [ca-skeleton]
tags: [official-doc, ca-skeleton, messaging, kafka, retry-policy, dead-letter-queue]
created: 2026-07-28
---
# official-doc / Spring for Apache Kafka — Non-Blocking Retry Topic Pattern (Ordering Loss)
> Layer: `raw/` — 외부 자료(공식 문서)의 **원문 발췌·출처 기록**.
> 문서 버전: Spring for Apache Kafka reference **4.1.0** (페이지 상단 버전 표기 기준, 2026-07-28 확인).
## Parent / 활용 branch
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-kafka-consumer-inbox-contract]] | ca-skeleton consumer 재시도 전략 선택 — non-blocking retry topic 체인이 파티션 정체를 피하는 대신 Kafka 의 순서 보장을 잃는다는 공식 자인이, per-aggregate(파티션 키) 순서 보장을 유지해야 하는 계약에서 이 대안을 언제 배제/채택할지의 선택 조건 근거 |
## 출처
- 원본 URL: https://docs.spring.io/spring-kafka/reference/retrytopic/how-the-pattern-works.html
- 아카이브 URL: (미제공)
- 저자 / 조직: Spring team (Broadcom / VMware Tanzu — Spring for Apache Kafka reference)
- 발행일: (reference 페이지 자체에 발행일 미표기 — 버전 4.1.0 기준 문서)
- 마지막 확인일: 2026-07-28
## 왜 저장했는지
ca-skeleton 의 `adapter:inbound:messaging-kafka` consumer 가 non-blocking retry topic 체인(retry topic + DLT)을 재시도 전략으로 채택할지 결정하려면, 이 패턴이 **Kafka 의 순서 보장을 잃는다**는 공식 자인을 근거로 per-aggregate 순서 보장 요구가 있는 leaf 에서 배제 조건을 판단해야 한다. 이 raw 문서는 그 배제/채택 판단의 1차 근거다.
## 핵심 인용
> [§How the Pattern Works] "If message processing fails, the message is forwarded to a retry topic with a back off timestamp."
> [§How the Pattern Works] "The retry topic consumer then checks the timestamp and if its not due it pauses the consumption for that topics partition."
> [§How the Pattern Works] "If the message processing fails again the message will be forwarded to the next retry topic, and the pattern is repeated until a successful processing occurs, or the attempts are exhausted, and the message is sent to the Dead Letter Topic (if configured)."
> [§How the Pattern Works] "To illustrate, if you have a "main-topic" topic, and want to set up non-blocking retry with an exponential backoff of 1000ms with a multiplier of 2 and 4 max attempts, it will create the main-topic-retry-1000, main-topic-retry-2000, main-topic-retry-4000 and main-topic-dlt topics and configure the respective consumers."
> [§How the Pattern Works] "By using this strategy you lose Kafkas ordering guarantees for that topic."
> 참고: 원문은 straight apostrophe(`'`)가 아니라 curly apostrophe(U+2019, ``)를 사용한다 (`its`, `topics`, `Kafkas`). 위 인용은 원문 문자 그대로(U+2019) 보존했으며, self-grep 검증도 동일 문자로 수행했다 — 아래 검증 로그 참조.
## Claims Extracted
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| SPRK-RETRYTOPIC-C1 | non-blocking retry topic 패턴은 처리 실패 메시지를 back-off timestamp 와 함께 별도 재시도 토픽으로 포워딩하고, 재시도 토픽 컨슈머는 그 timestamp 가 도래하기 전까지 **해당 토픽 파티션의 소비 자체를 일시 중지**한다 | [§How the Pattern Works] "If message processing fails, the message is forwarded to a retry topic with a back off timestamp." + "The retry topic consumer then checks the timestamp and if its not due it pauses the consumption for that topics partition." | `official-vendor-doc` | Spring for Apache Kafka 의 `@RetryableTopic`/`RetryTopicConfiguration` non-blocking retry 기능 (reference 4.1.0) | 이 메커니즘이 raw Kafka client(Spring 미사용) 컨슈머에도 그대로 적용된다는 것 |
| SPRK-RETRYTOPIC-C2 | 재시도가 반복 실패하면 다음 재시도 토픽으로 계속 포워딩되다가, 시도 횟수 소진 시(그리고 DLT 가 설정된 경우) Dead Letter Topic 으로 전송된다 | [§How the Pattern Works] "If the message processing fails again the message will be forwarded to the next retry topic, and the pattern is repeated until a successful processing occurs, or the attempts are exhausted, and the message is sent to the Dead Letter Topic (if configured)." | `official-vendor-doc` | 동일 non-blocking retry 기능의 종료 조건 | DLT 전송이 항상 강제된다는 것 — 원문의 "(if configured)"는 DLT 가 선택 설정임을 명시 |
| SPRK-RETRYTOPIC-C3 | 이 전략(non-blocking retry topic 체인)을 사용하면 **해당 토픽의 Kafka 순서 보장을 잃는다** — 공식 문서가 직접 자인하는 trade-off | [§How the Pattern Works] "By using this strategy you lose Kafkas ordering guarantees for that topic." | `official-vendor-doc` | non-blocking retry topic 전략을 채택하는 임의 토픽 — per-aggregate(파티션 키) 순서 보장이 필요한 leaf 에서 이 전략을 배제/채택할지 판단하는 결정적 근거 | blocking retry 가 전반적으로 우월하다는 것은 아님 — 순서 손실의 정량적 영향(예: 얼마나 자주, 어느 범위까지)은 명시하지 않으며, 파티션 키 설계로 순서 손실을 완화할 수 있는지도 이 문장만으로는 증명 못 함 |
| SPRK-RETRYTOPIC-C4 | 예시 설정(1000ms 백오프, multiplier 2, 최대 4회 시도)에서 프레임워크는 `<topic>-retry-<backoffMs>` 형태의 재시도 토픽들과 `<topic>-dlt` 토픽을 **자동 생성**하고 리스너까지 구성한다 | [§How the Pattern Works] "it will create the main-topic-retry-1000, main-topic-retry-2000, main-topic-retry-4000 and main-topic-dlt topics and configure the respective consumers." | `official-vendor-doc` | 기본(커스터마이징 없는) 토픽 명명 및 자동 생성 동작의 예시 | 이 예시가 보여주는 것은 특정 백오프 설정(1000ms×2, 4회)에서의 네이밍이며, `-retry`/`-dlt` 단독 접미사가 모든 설정에서 고정된 기본값이라는 일반 규칙은 별도 "Topic Naming" reference 페이지 소관 — 이 URL(1 dispatch = 1 URL 원칙) 로는 확인하지 않음, **미발견** |
## Usage Boundaries
- 이 자료가 직접 증명하는 것:
- `SPRK-RETRYTOPIC-C1`, `SPRK-RETRYTOPIC-C2`: non-blocking retry topic 패턴의 동작 메커니즘(timestamp 기반 pause/resume, 시도 소진 시 DLT)
- `SPRK-RETRYTOPIC-C3`: 이 전략이 해당 토픽의 Kafka 순서 보장을 깨뜨린다는 공식 자인 — per-aggregate 순서 보장이 필요한 consumer 설계에서 이 대안을 배제할지 판단하는 결정적 근거
- `SPRK-RETRYTOPIC-C4`: 특정 백오프 설정 예시에서의 토픽 자동 생성/명명 동작
- 이 자료가 증명하지 않는 것:
- blocking retry(동일 파티션 내 backoff) 전략이 순서를 보존하면서도 처리량/지연 측면에서 더 우월하다는 것 — 이 문서는 trade-off 의 한쪽(순서 손실)만 자인할 뿐 대안 비교를 제공하지 않음
- `-retry`/`-dlt` 접미사가 모든 backoff 설정에서 고정된 기본값이라는 일반 규칙 (Topic Naming 별도 페이지 소관, 이 dispatch 범위 밖)
- AckMode·`seekAfterError` 관련 문장(원문에 존재하나 본 raw 문서는 ca-skeleton 결정 근거로 요청된 순서 손실/패턴 동작/명명에 집중해 별도 Claim 화하지 않음 — 필요 시 후속 raw 문서로 분리)
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- ca-skeleton `adapter:inbound:messaging-kafka` 의 실제 파티션 키 설계(예: aggregate id 기반)가 이 순서 손실 trade-off 를 어느 leaf 에서 감수 가능한지/불가능한지 branch-local 결정(D-row)으로 명시 필요
- 이 전략을 채택할 경우 `InboxStorePort` 멱등 계약과의 상호작용(재시도 토픽에서 재처리되는 메시지의 멱등 판정) 검증 필요 — sibling branch `feature-idempotency-ownership-protocol-contract` 소관
## 메모
- 인용 해석 후보(미검증): 순서 손실은 "해당 토픽" 단위로 발생하므로, 만약 재시도 토픽을 원본과 동일 파티션 키로 구성한다면 같은 key 의 메시지끼리는 재시도 토픽 내에서 여전히 순서가 섞일 수 있음 — 이 문서만으로는 파티션 키 유지 여부에 따른 완화 가능성을 확인할 수 없음 (검증 필요)
- 추가로 봐야 할 동일 출처 페이지: `retrytopic/topic-naming.html`(기본 접미사 커스터마이징 규칙), `retrytopic/features.html`(추가 옵션), `retrytopic/dlt-strategies.html`(DLT 처리 전략) — 각각 별도 dispatch 로 수집
## Related
- 같은 주제 다른 official-doc / company-tech-blog: (아직 없음 — Kafka 공식 consumer configs·rebalance 문서는 `feature-kafka-consumer-inbox-contract` 의 "추가 수집 필요" 항목으로 남아 있음)
- 이 자료를 인용한 wiki 요약: (생성 시 링크)