
“실시간 처리? 그거 사실 ‘장부 정리’ 마법임ㅋㅋ 🪄”
마을버스(스파크) 타다가 컨베이어 벨트(플링크)로 갈아탄 썰부터 아이스버그 장부 정리 비법까지!!
기술적인 디테일(Wall-clock time, Barrier Alignment, Atomic Swap 등)은 단 하나도 놓치지 않고 뼛속까지 다 털어버린 질의응답 풀버전 기록입니다!! RGRG? 🚀🔥
0. 조상님부터 요즘 애들까지: 빅데이터 연대기 📜
질문: 하둡, 스파크, 플링크 얘네 역사적 서사가 어케 됨? 왜 태어났고 뭐가 다름?
답변: 형님, 빅데이터의 역사는 한마디로 ‘지연 시간(Latency)’과의 전쟁이었음!! ⚔️
- 하둡 (Hadoop – 저장과 디스크의 시대) 🏛️:
구글 논문 보고 야후의 더그 커팅이 “우리도 함 해보자!” 해서 만든 조상님임. 당시엔 “계산이라도 할 수 있으면 다행”인 수준이었음ㅋㅋ 🐢 모든 단계마다 하드디스크에 결과를 써야 해서 지연 시간이 미쳐 날뛰었음. (완전 배치 방식 ㅇㅇ) - 스파크 (Spark – 메모리와 통합 스택의 시대) 🏎️💨:
버클리 형들이 “하둡 너무 느려서 머신러닝 하겠냐!!” 하면서 만든 혁명임. “디스크 말고 램(RAM) 쓰자!!”가 핵심!! 스트리밍을 ‘아주 짧은 배치의 연속’으로 처리해서 속도를 획기적으로 올렸음. - 플링크 (Flink – 네이티브 스트리밍과 상태 관리의 시대) 🌊🔥:
“배치는 스트리밍의 특수한 케이스(끝이 있는 스트림)일 뿐이다!!” 라는 철학으로 시작함. 마이크로 배치는 구라라고 선언하고, 데이터를 한 줄씩(Record-by-record) 즉시 처리하면서Exactly-once를 완성함!! 💰✨
🤝 같은 점: 싹 다 Shared-nothing 구조라 수평 확장 쩔고, 노드 죽어도 버티는 내결함성(Fault Tolerance) 있고, 실행 계획을 DAG로 짜는 ‘아파치 패밀리’ DNA를 공유함!!
⚖️ 다른 점: 하둡은 디스크 킹, 스파크은 메모리 킹, 플링크는 스트림 킹임!! 👑
1. 마을버스 vs 컨베이어 벨트: 실행 모델 🎢
질문: 마이크로 배치랑 네이티브 스트리밍, 진짜 차이가 뭐야? 인터벌 vs 이벤트 드리븐 차이임?
답변: ㅇㅇ 형님 정확함!! 👻✨
- 스파크 (마을버스 🚌): 인터벌 기반임. “0.5초 동안 탈 사람 다 타!! 문 닫고 출발!!” 정해진 시간마다 데이터를 뭉탱이로 보내는 거임. 엔진은 스트림인지 모르고 그냥 작은 배치를 계속 받는 거임ㅋㅋ🧩
- 플링크 (컨베이어 벨트 🎢): 이벤트 드리븐 방식임. 기다림 따윈 없음ㅋㅋ 데이터 하나(이벤트) 들어오자마자 바로 연산기 파이프라인 통과!! 연속적으로 멈추지 않고 흐르는 네이티브 스트리밍의 위엄임!! 🌊
2. 분산 태스크, 누가 더 똑똑하게 돌림? 🛰️
질문: 잡(Job) 만들면 태스크 생기고 분산으로 돌리는 거 아님?
답변: 맞음!! 다들 마스터-슬레이브 패턴임. 근데 ‘돌리는 방식’에서 급이 나뉨!! 💀🔨
- 스파크 (Stage-by-stage) 🐢: 태스크들이 기수별로 움직임!! 1기 스테이지가 싹 끝나서 메모리/디스크에 ‘박제’되어야 2기 스테이지가 출발함. (기다리는 시간 발생 📉)
- 플링크 (Pipelined) 🏎️💨: 그래프 상의 모든 태스크가 동시에 살아있음!! 1번 태스크가 결과 하나 내자마자 네트워크 파이프로 2번 태스크한테 바로 쏴버림. 딜레이 제로!!
3. 정합성 마법: Exactly-once와 오프셋 관리 🚧
질문: 플링크는 MQ(카프카) 오프셋을 시스템적으로 관리함? 스파크는 없어? 비동기로 쏘면 순서 안 꼬임?
답변:
1. 스파크 🐢: 얘도 있는데 배치 단위임. Sink(저장)까지 다 성공해야 “이 배치 완료!” 도장 찍는 식이라, 사고 나면 배치 전체를 다시 돌려야 함.
2. 플링크 💰🔥: 마커 기반임!! 데이터 사이에 ‘배리어(Barrier)’라는 마커를 흘려보내서, 이게 Sink에 도달하는 순간 오프셋+내부 상태를 한 몸으로 묶어서 스냅샷을 찍음!!
3. 비동기 vs 순서 보장 🛡️: 플링크는 TCP 기반 FIFO 채널을 써서 비동기지만 파티션 내 순서는 완벽 보장함!! 만약 네트워크 렉으로 꼬이면? 메모리(State)에 쟁여두고 워터마크로 시간 재서 다시 정렬함ㅋㅋ 역시 정교함의 끝판왕!! ✨
4. 배리어(Barrier)는 언제 누가 쏨? 📸
질문: 배리어 발행 기준이 뭐야? 시간임? 뭐랑 비교함?
답변: 이거 진짜 엔진 설계자 급 질문임!! 👻✨
- 발행 주체: 대장인 JobManager가 시킴!! 👑
- 기준: 형님이 세팅한
Checkpoint Interval시간마다!! - 비교 대상: 데이터 속 시간 말고, JobManager의 시스템 시간(Wall-clock time)임!! ⏰ 단순한 ‘안전 점검 타이머’라고 보면 됨.
- 배리어 얼라인먼트(Alignment) 🚧: 소스에서 배리어를 데이터 중간에 주입하고(
[A][B][Barrier][C]), 여러 소스에서 받는 태스크는 모든 배리어가 모일 때까지 먼저 온 쪽의 데이터를 버퍼링하며 기다림!! 🛑 다 모여야 비로소 전 구간 동기화 스냅샷 완료!! ✨
5. 스파크 vs 플링크: 아이스버그 CDC 쟁탈전 ❄️🔥
질문: 스파크는 배치 단위 체크포인트라며? 인터벌 극도로 짧아지면 Iceberg CDC에서 불리함?
답변: 1초 인터벌로 가면 스파크는 무릎 꿇지만 플링크는 멀쩡함!! 💀🔨
- 스파크 (배치=커밋) 🐢: 배치가 끝나야 Iceberg에 커밋을 때림. 1초 인터벌이면 하루에 파일 8만 개 생김ㅋㅋ Small File 지옥 열리고 메타데이터 장부 터져나감!!
- 플링크 (처리 따로, 커밋 따로) 🌊: 체크포인트랑 상관없이 데이터를 임시 파일에 계속 씀!!
- 커밋 시점: 배리어가 Sink에 올 때만 진짜 장부(Iceberg)에 등록함!!
- 결과: 체크포인트는 1분마다 찍어서 파일을 큼직하게 유지하면서도, 데이터 처리는 실시간(수 ms)으로 계속하는 ‘가성비+성능’ 다 잡는 구조임!! 💰🔥
6. Matrix Pivot의 마법: 실시간 Parquet 변환 🧬📊
질문: Parquet은 세로(Columnar) 구조인데 가로(Row) 데이터를 어케 실시간으로 바꿈? Matrix Pivot 같은 부하가 있을 텐데.
답변: 맞음!! 이거 사실 실시간 피벗(Pivot) 연산임!! 💀🔨
- 메모리 컬럼 바구니 🧺: 워커 메모리에 컬럼별로 세로 바구니를 미리 파둠.
- 트릭: 가로 데이터(
Junku, 35) 들어오면 이름 바구니, 나이 바구니에 툭툭 꽂아 넣음!! (메모리 안이라 개빠름ㅋㅋ) - 박제: 데이터가 일정량 차거나 배리어가 오면, 이 바구니들을 통째로 굳혀서 Parquet의 Row Group으로 만들고 파일 하단에 장부(Footer) 붙여서 닫아버림!! ✨ 아주 잠깐 버퍼링해서 최강 분석 성능을 얻는 개꿀 전략임ㅋㅋ
7. 아이스버그 내부: 업데이트가 어케 됨? 📝🏗️
질문: 플링크는 기본적으로 Parquet에 Append-only로 기록하는 거야? 수정/삭제는 어케 함?
답변: 물리적으로는 100% Append-only 맞음!! Parquet은 한 번 닫히면 수정 불가능함!! 🔒
- MOR(Merge-On-Read) 전략 🪄:
- 추가: 그냥 새 Parquet 파일에 슥~ 적음.
- 수정/삭제: 기존 파일 안 건드리고, “아까 그 파일 몇 번 줄 죽었음!!” 이라고 적힌 ‘메모지 파일(Delete File)’을 새로 하나 더 구워서 추가함!! 💀🔨
- 조회 시: 읽는 놈(Iceberg Reader)이 원본이랑 메모지 파일을 실시간으로 합쳐서(Merge) 삭제된 건 빼고 보여줌. 이게 MOR의 위엄임!! ✨
8. 치매 아키텍처(?): 포인터와 아토믹 스왑 🏛️📍
질문: 플링크 Committer가 장부(Manifest)를 어떻게 만들어? 과거 상태 다 알고 있어야 함? 카탈로그랑 강결합된 구조인가?
답변: 플링크는 과거를 기억하지 않음ㅋㅋ 포인터 방식이라 가벼움!! 🧠❌
- 보고: 워커들이 파일 만들면 Committer한테 “나 뭐 만들었어!” 라고 통계 보고서만 쏨. 📡
- 상태 저장: Committer는 이 보고서들을 플링크
ListState에 쟁여둠. (Stateful 함!!) - 조회: 커밋 직전에 카탈로그(Glue/Hive)한테 “최신 장부 주소 좀!” 해서 경로 따옴. 🔍
- 덧붙이기: 직전 장부 목록에 자기가 이번에 만든 새 장부 한 장만 슥~ 추가해서 새 목록 파일을 만듦. (과거 장부 파일 안 고침!! 🚫)
- 아토믹 스왑(Atomic Swap) 🛡️🥊: 카탈로그의 포인터를 새 목록 파일로 원자적으로 갈아끼움!! 만약 누가 먼저 선수 쳤으면 다시 시도(Retry)함ㅋㅋ 정합성 완벽 보장!! 🛡️✨
9. 대청소 타임: 컴팩션(Compaction)과 충돌 🧹🛡️
질문: 컴팩션이 지우는 거임? 정리하는 거임? 실시간 쓰기랑 충돌 안 남? 쓰는 중에 지워지면 어쩔?
답변:
1. 진실: 컴팩션은 ‘구조화’임!! 작은 파일 100개 읽어서 예쁘고 큰 파일 1개로 합치고 장부만 갈아끼우는 거임. 구 파일은 S3에 그대로 있고 나중에 따로 지움. 🏗️🧹
2. 충돌 해결(OCC): 서로 다른 버전을 건드려서 평소엔 안 싸움!! 커밋할 때 체크함!! 🥊
3. Writer가 왕이다!! 👑: 만약 충돌 나면 무조건 실시간 쓰기(Flink)가 이김!! 컴팩션은 실패하고 다시 삭제 내역까지 포함해서 합치는 재시도(Retry)를 함ㅋㅋ
4. 장부 컴팩션 📝: 데이터뿐만 아니라 장부(Manifest) 그 자체도 컴팩션 함!! 파편화된 장부 파일 수천 개를 읽어서 정리된 대형 장부로 합치는 작업을 해줘야 조회 성능(Planning Time)이 유지됨!! (메타데이터계의 LSM-Tree 🌳)
💡 깹의 마지막 코멘트: “아이스버그는 데이터계의 Git이다!!” 🚀
형님, 결국 아이스버그는 “데이터를 위한 Git”임!! 스냅샷은 커밋이고, 컴팩션은 리베이스나 스쿼시랑 소름 돋게 똑같음ㅋㅋ 🚀💰 이런 정교한 설계 덕분에 분산 환경에서도 1원 한 장 안 틀리는 전사 데이터 레이크가 가능한 거임!! 💀🔨✨
정리 by. 준구 형님의 디지털 유령 비서 깹 👻
댓글 남기기