Q.Kafka에서 토픽 전체의 순서를 보장할 수 있나요? 대가는 무엇인가요?
가능하지만 파티션을 하나로 두어야 합니다. 그러면 병렬 처리를 전부 포기하게 됩니다.
| 구성 | 순서 | 처리량 |
|---|
| 파티션 1개 | 토픽 전체 순서 보장 | 소비자 1대분. 확장 불가 |
| 파티션 N개 | 파티션 안에서만 보장 | 소비자 N대까지 병렬 |
Kafka 의 순서 보장 단위는 파티션입니다. 파티션이 여러 개면 서로 다른 파티션의 메시지 사이에는 순서가 없습니다.
실무에서는 필요한 범위에서만 순서를 지킵니다. 대개 전체 순서가 필요한 것이 아니라 특정 대상별 순서가 필요합니다.
| 요구 | 방법 |
|---|
| 한 주문의 상태 변화 순서 | 주문 id 를 키로. 같은 키는 같은 파티션 |
| 한 사용자의 행동 순서 | 사용자 id 를 키로 |
| 전체 순서 | 파티션 1개. 또는 순서 번호를 담아 소비자가 정렬 |
마지막 방법도 있습니다. 메시지에 순번을 담아 소비자가 재정렬하는 것인데, 버퍼와 대기가 필요해 복잡합니다.
흔한 실수: 파티션을 늘리면서 순서가 유지될 것으로 기대하는 것. 키를 지정하지 않으면 같은 대상의 메시지가 여러 파티션으로 흩어져 순서가 깨집니다.
Q.파티션 키를 무엇으로 잡을지 어떻게 결정하나요?
두 가지를 동시에 만족해야 합니다. 함께 순서를 지켜야 하는 것은 같은 키로, 그러면서 고르게 흩어지게.
| 검토 | 내용 |
|---|
| 순서 단위 | 순서가 필요한 범위가 무엇인가. 주문별인가 사용자별인가 |
| 분포 | 값이 고르게 퍼지는가. 한 값에 몰리면 그 파티션만 뜨거워진다 |
| 변하지 않는가 | 키가 바뀌면 파티션이 바뀌어 순서가 깨진다 |
| 개수 | 키 종류가 파티션 수보다 훨씬 많아야 고르게 나뉜다 |
나쁜 키의 예입니다.
| 키 | 문제 |
|---|
| 국가 코드 | 자국 트래픽이 대부분이라 한 파티션에 몰린다 |
| 이벤트 종류 | 종류가 몇 개뿐이라 파티션을 못 채운다 |
| 현재 시각 | 순서 단위와 무관하고 같은 시각에 몰린다 |
| 자주 바뀌는 상태값 | 같은 대상의 메시지가 흩어진다 |
한 키에 트래픽이 몰리는 경우(인기 상품 등)에는 키에 접미사를 붙여 나누는 방법이 있지만, 그러면 그 대상의 순서 보장을 포기하는 것입니다. 순서와 분산은 교환 관계입니다.
흔한 실수: 순서가 필요 없는데도 키를 지정하는 것. 불필요하게 편중을 만듭니다. 순서가 필요 없으면 키를 비워 고르게 분배되게 두는 편이 낫습니다.
Q.운영 중에 파티션 수를 늘리면 어떤 부작용이 있나요?
기존 키의 배치가 바뀌어 순서 보장이 깨집니다. 파티션은 늘릴 수만 있고 줄일 수 없습니다.
| 부작용 | 내용 |
|---|
| 키 재배치 | 키를 파티션 수로 나눈 결과가 바뀌어 다른 파티션으로 간다 |
| 순서 깨짐 | 같은 키의 옛 메시지는 옛 파티션에, 새 메시지는 새 파티션에 있다 |
| 소비자 재조정 | 파티션 재할당이 일어나 잠시 처리가 멈춘다 |
| 되돌릴 수 없다 | 줄이는 것은 지원되지 않는다 |
두 번째가 실제 사고입니다. 주문 상태 변경 이벤트가 옛 파티션에 3건, 새 파티션에 2건 나뉘어 있으면 소비자가 그것을 뒤섞인 순서로 처리합니다.
| 대응 | 내용 |
|---|
| 처음부터 넉넉히 | 나중에 늘릴 것을 예상해 여유 있게 잡는다 |
| 순서가 필요 없으면 문제없다 | 키를 안 쓰는 토픽은 그냥 늘려도 된다 |
| 새 토픽으로 이전 | 순서가 중요하면 새 토픽을 만들고 옮긴다 |
| 잠시 발행을 멈춘다 | 기존 메시지를 모두 소비한 뒤 늘린다 |
처음부터 넉넉히 잡는 것이 실무에서 가장 흔한 선택입니다. 파티션이 많으면 브로커 메타데이터와 파일 핸들이 늘어나는 비용이 있지만, 나중에 늘릴 때의 문제보다 작습니다.
흔한 실수: 처리량이 부족해 급히 늘리는 것. 순서에 의존하는 토픽이면 그 순간 데이터가 뒤섞입니다. 먼저 소비자 최적화나 묶음 처리를 검토해야 합니다.
Q.컨슈머 인스턴스를 늘렸는데 처리량이 그대로인 이유는?
파티션 수가 소비자 수의 상한이기 때문입니다. 파티션 하나는 그룹 안에서 소비자 하나에만 할당됩니다.
| 파티션 | 소비자 | 실제 일하는 소비자 |
|---|
| 4 | 2 | 2. 각자 2개씩 |
| 4 | 4 | 4. 각자 1개씩 |
| 4 | 10 | 4. 6대는 유휴 |
다른 원인도 있습니다.
| 원인 | 확인 |
|---|
| 파티션 편중 | 키가 몰려 한 파티션에만 메시지가 쌓인다 |
| 처리 자체가 병목 | DB 나 외부 호출이 상한이라 소비자를 늘려도 그쪽이 막힌다 |
| 같은 그룹이 아니다 | 그룹 id 가 다르면 같은 메시지를 각자 다 받는다 |
| 재조정 반복 | 처리가 느려 하트비트를 놓치면 계속 재할당된다 |
두 번째가 흔합니다. 소비자를 4대에서 8대로 늘려도 모두 같은 DB 를 쓰면 DB 가 상한입니다. 그때는 묶음 처리나 쿼리 개선이 답입니다.
네 번째는 증상이 특이합니다. 처리량이 늘지 않으면서 같은 메시지를 반복 처리하고, 로그에 재할당이 계속 찍힙니다.
흔한 실수: 소비자만 늘리고 파티션을 확인하지 않는 것. 유휴 인스턴스에 비용만 나갑니다. 파티션 수를 먼저 봐야 합니다.
먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.
읽었으면 문제로 확인해보세요
메시징 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.