同じキーは同じパーティションへ — ログを実際に操作する
한국어 원문으로 표시합니다.
이 실습은 VM 에서 돕니다
우분투 VM 에 Apache Kafka 4.3.1 이 KRaft 단일 노드로 떠 있습니다(systemd
kafka 서비스, localhost:9092). /opt/kafka/bin 이 PATH 에 있어 kafka-topics.sh
같은 도구를 바로 쓸 수 있습니다. 처음 뜨는 데 4분쯤 걸립니다.
목표
토픽을 만들고 키가 있는 이벤트를 넣어, 같은 키가 같은 파티션으로 가고 파티션 안에서 순서가 지켜지는 것을 봅니다. 컨슈머 그룹의 오프셋과 지연(lag)을 읽고, 두 그룹이 서로 독립적으로 읽는 것을 확인한 뒤, 파티션 수를 늘리면 키 배치가 바뀌는 것을 직접 관찰합니다.
왜 중요한가
"주문이 두 번 도착했고 한 번은 사라졌다" 는 사고를 읽으려면 먼저 Kafka 가 무엇을 약속하고 무엇을 약속하지 않는지 알아야 합니다. Kafka 는 파티션 안의 순서만 약속합니다. 같은 키가 같은 파티션으로 가기 때문에 주문 하나의 이벤트 순서는 지켜지지만, 다른 주문끼리는 아닙니다. 그리고 소비된 메시지는 지워지지 않습니다 — 컨슈머 그룹마다 "어디까지 읽었나" 하는 정수 하나(오프셋)를 따로 갖기 때문에, 한 그룹이 놓친 것을 다른 그룹은 처음부터 다시 읽을 수 있습니다. 이 두 가지가 뒤 모듈의 중복·유실 이야기의 바탕입니다.
단계
- 토픽
orders를 파티션 3개로 만드세요. /root/kafka/orders.txt의 아홉 줄(키:값형식)을kafka-console-producer.sh로 키를 파싱해서 넣으세요. 여러 파티션에 나뉘어 들어가야 합니다.- 파티션·오프셋·키가 보이게 처음부터 전부 읽어
/root/kafka/keyed.txt에 저장하세요. 같은 키는 한 파티션에만 있어야 합니다. - 컨슈머 그룹
order-svc로 처음부터 아홉 건을 읽고, 그 그룹을 describe 한 결과를/root/kafka/group.txt에 저장하세요. /root/kafka/more.txt의 세 줄을 더 넣고(읽지는 말고)order-svc를 다시 describe 해/root/kafka/lag.txt에 저장하세요. LAG 이 보여야 합니다.- 두 번째 그룹
analytics로 처음부터 열두 건을 읽으세요.order-svc의 오프셋은 그대로여야 합니다. orders를 파티션 6개로 늘리고order-1:refunded를 넣은 뒤 처음부터 읽어/root/kafka/repartition.txt에 저장하세요. 그리고/root/kafka/repartition-report.txt에partitions_before=3,partitions_after=6,order1_before=<3단계에서 order-1 이 있던 파티션>,order1_after=<refunded 가 들어간 파티션>네 줄을 쓰세요.
참고
- 키 파싱:
--reader-property parse.key=true --reader-property key.separator=:(4.3 에서--property는 deprecated 입니다). - 읽을 때 메타데이터 표시:
--formatter-property print.key=true --formatter-property print.partition=true --formatter-property print.offset=true. 출력은Partition:0\tOffset:0\t키\t값꼴입니다. - 컨슈머는
--from-beginning --max-messages N --timeout-ms 8000으로 N 건을 읽으면 끝냅니다. 없으면 Ctrl-C 를 눌러야 합니다. - 그룹 상태:
kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group <이름>. 컨슈머가 끝난 뒤에는 "has no active members" 가 나오지만 오프셋 표는 그대로 보입니다. - 파티션 늘리기:
kafka-topics.sh ... --alter --topic orders --partitions 6. 줄이는 것은 지원되지 않습니다(운영 문서). - 흔한 실수 1:
--max-messages없이--timeout-ms만 주면 마지막 메시지 뒤에 그 시간을 더 기다립니다. 둘 다 주세요. - 흔한 실수 2: 파티션 수를 바꾼 뒤 옛 데이터가 옮겨질 것으로 기대하는 것. Kafka 는 기존 데이터를 재배치하지 않습니다.
파티션 3개짜리 토픽
토픽 orders 를 파티션 3개로 만드세요.
kafka-topics.sh --bootstrap-server localhost:9092 --create --topic ... --partitions 3. 만든 뒤 --describe 로 PartitionCount 를 확인하세요.
키가 있는 이벤트를 넣는다
/root/kafka/orders.txt 의 아홉 줄(키:값 형식)을 kafka-console-producer.sh 로 키를 파싱해서 넣으세요. 여러 파티션에 나뉘어 들어가야 합니다.
--reader-property parse.key=true --reader-property key.separator=: 를 주고 파일을 표준 입력으로 넘기세요. 키를 파싱하지 않으면 한 줄 전체가 값이 되고 키가 null 이라 파티션이 키와 무관하게 정해집니다.
파티션과 오프셋을 눈으로 본다
파티션·오프셋·키가 보이게 처음부터 전부 읽어 /root/kafka/keyed.txt 에 저장하세요. 같은 키는 한 파티션에만 있어야 합니다.
--from-beginning --max-messages 9 --timeout-ms 8000 에 --formatter-property print.key=true --formatter-property print.partition=true --formatter-property print.offset=true 를 더하고 출력을 파일로 보내세요. 파티션끼리는 순서가 섞여 나오지만 한 파티션 안에서는 오프셋이 오릅니다.
컨슈머 그룹의 오프셋
컨슈머 그룹 order-svc 로 처음부터 아홉 건을 읽고, 그 그룹을 describe 한 결과를 /root/kafka/group.txt 에 저장하세요.
--group order-svc 를 주면 읽은 위치가 브로커에 커밋됩니다. 끝난 뒤 kafka-consumer-groups.sh --describe --group order-svc 의 CURRENT-OFFSET 이 파티션마다 LOG-END-OFFSET 과 같고 LAG 이 0 이어야 합니다.
읽지 않으면 지연이 쌓인다
/root/kafka/more.txt 의 세 줄을 더 넣고(읽지는 말고) order-svc 를 다시 describe 해 /root/kafka/lag.txt 에 저장하세요. LAG 이 보여야 합니다.
2단계와 같은 방법으로 넣되 컨슈머는 돌리지 마세요. LOG-END-OFFSET 은 오르고 CURRENT-OFFSET 은 그대로라 그 차이가 LAG 입니다.
그룹은 서로 독립이다
두 번째 그룹 analytics 로 처음부터 열두 건을 읽으세요. order-svc 의 오프셋은 그대로여야 합니다.
--group analytics --from-beginning --max-messages 12. 소비된 메시지는 지워지지 않으므로 새 그룹은 처음부터 전부 읽을 수 있고, 다른 그룹의 오프셋에는 아무 영향이 없습니다.
파티션을 늘리면 키 배치가 바뀐다
orders 를 파티션 6개로 늘리고 order-1:refunded 를 넣은 뒤 처음부터 읽어 /root/kafka/repartition.txt 에 저장하세요. 그리고 /root/kafka/repartition-report.txt 에 partitions_before=3, partitions_after=6, order1_before=<3단계에서 order-1 이 있던 파티션>, order1_after=<refunded 가 들어간 파티션> 네 줄을 쓰세요.
--alter --topic orders --partitions 6 뒤에 키 파싱으로 한 줄을 넣고, 3단계처럼 --max-messages 13 으로 읽으세요. 운영 문서가 말하듯 기본 파티셔너는 hash(key) % 파티션 수 라서 파티션 수가 바뀌면 같은 키가 다른 파티션으로 갈 수 있고, 기존 데이터는 옮겨지지 않습니다.