EMR + Iceberg + S3 Table Bucket 환경에서 SHOW TABLES가 멈추던 문제EMR에서 Iceberg 테이블을 운영하던 중,SHOW TABLES가 느린 수준을 넘어실제로 멈춘 것처럼 보이는 현상을 겪었다.쿼리는 실패하지 않았고 에러 로그도 남지 않았지만,Spark driver는 더 이상 진행되지 않는 상태였다.겉으로 보면 catalog가 멈춘 것처럼 보였다.문제 상황운영 환경은 다음과 같았다. AWS EMR Spark + Iceberg Glue Catalog Iceberg 테이블은 S3 Table Bucket(S3Tables) 기반문제가 발생한 쿼리는 단순했다.SHOW TABLES IN some_database;관찰된 증상은 다음과 같았다. 수 초에서 수 분 이상 응답이 ..
Hot Partition 증상전체 TPS 는 여유가 있는데 특정 파티션의 lag만 지속 증가해당 파티션의 리더 브로커 CPU/Network 100%컨슈머 스케일 아웃해도 효과가 없다. 원인key -> hash -> partition 구조한 파티션에 트래픽 집중병렬성 상실 대응해당 파티션 lag, bytes-in, records-in 즉시 모니터링컨슈머를 늘려도 효과 없음을 빠르게 확인해당 key를 별도 토픽으로 분리 구조적 개선user_id + N hash: 같은 유저더라도 여러개 파티션 사용하게 변경. 그 대신, 순서 정렬은 포기해야 한다.별도 토픽으로 분리(SLA, retention, consumer) 별도 운영Rabalance Storm 증상컨슈머 lag가 급증후 회복로그 Rebalance in p..
Apache Kafka는 높은 처리량, 분산 메시징, 내결함성, 확장성을 제공하는 이벤트 스트리밍 플랫폼입니다.Kafka는 수천 TPS 수준의 데이터 스트림을 안정적으로 처리하면서프로듀서, 브로커, 컨슈머 패턴으로 생산/소비를 분리해줍니다. 또한 Kafka는 로그 정합성 보장, partition 기반 병렬 처리, offset 관리를 통해 장애 복구 시점 선택이나 재처리(replay)도 가능합니다.이런 성질 때문에 실시간 스트리밍 처리 파이프라인, CDC(변경 데이터 캡처), 이벤트 소싱ㅇ 아키텍처 등에 널리 사용됩니다.높은 처리량 1. 파티션 수한 파티션은 한 컨슈머 인스턴스가 독점 소비합니다.처리량을 올리려면 파티션수 >= 컨슈머 병렬 수가 기본 전제.단, 파티션을 무작정 늘리면 컨트롤 오버헤드(메타데..
https://xelloss111.tistory.com/67 sudo alterna" data-og-host="xelloss111.tistory.com" data-og-source-url="https://xelloss111.tistory.com/67" data-og-url="https://xelloss111.tistory.com/67" data-og-image="https://blog.kakaocdn.net/dna/hQdW0/hyZQ7yrRyj/AAAAAAAAAAAAAAAAAAAAAMMChvPvkX7ntAe89eudXns18NwzowKdo_k0aHGq5RqP/img.png?credential=yqXZFxpELC7KVnFOS48ylbz2pIh7yKj8&expires=1769871599&allow_ip=&allow_referer=&signature=0VsgAx1kCyBzOaFI%2FD5lvag1jAE%3D
https://tobuymacbookpro.tistory.com/entry/%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85-PermittedSubclasses-requires-ASM9-%EC%97%90%EB%9F%AC [트러블슈팅] PermittedSubclasses requires ASM9 에러김영한 선생님 자바 코드를 스프링부트 3.1.5로 업글하면서 발생한 문제. gradle 버전 충돌 문제다 프로젝트 이름/gradle/wrapper/gradle-wrapper.properties distributionUrl=https\://services.gradle.org/distributions/gradle-7.tobuymacbookpro.tistory.comgradle ver..
.├── README.md├── envs│ ├── _common│ │ ├── main.tf│ │ └── outputs.tf│ ├── dev│ │ ├── main.tf│ │ ├── terraform.tfstate│ │ └── terraform.tfstate.backup│ ├── prd│ │ ├── main.tf│ │ ├── terraform.tfstate│ │ └── terraform.tfstate.backup│ └── shared│ ├── main.tf│ ├── outputs.tf│ ├── terraform.tfstate│ └── terraform.tfstate.backup├── lambda..
Spark Dynamic Allocation의 핵심 원리Spark의 Dynamic Allocation은DAG 구조나 쿼리 복잡도를 기준으로 리소스를 배치하지 않는다.Spark는 실행 중인 애플리케이션의 상태를 지속적으로 관찰하며,오직 두 가지 신호에 반응한다.Task Backlog: 실행되지 못하고 대기 중인 task가 있는가Idle Executor: 할 일이 없는 executor가 일정 시간 이상 유지되는가이 두 상태에 따라 executor 수를 동적으로 조절한다.Backlog가 쌓이면: Scale-outSpark SQL 쿼리가 실행되면, stage 진입 시 대량의 task가 생성된다.이때 executor의 core 슬롯보다 task 수가 많아지면, 일부 task는 즉시 실행되지 못하고 backlog ..
Kafka 파티션이 늘어나면 병렬도는 어떻게 증가하는가Kafka에서 파티션은 병렬 처리의 최소 단위다.Spark Streaming(Structured Streaming 포함)은 매 배치마다 각 Kafka 파티션에 대해 “이번 배치에서 읽을 offset 구간”을 계산하고, 이 구간을 하나의 task로 만들어 처리한다.이 구조 때문에 Kafka 파티션 수가 늘어나면, 한 배치에서 동시에 생성될 수 있는 task 수의 상한도 함께 늘어난다.즉,Kafka 파티션 수 증가 → 동시에 실행 가능한 task 수 증가 → 병렬도 증가라는 인과관계는 명확하게 성립한다.그래서 “Kafka 파티션을 늘리면 병렬도가 높아진다”는 말 자체는 원리적으로 정확한 설명이다.단, 병렬도의 ‘상한’이 늘어나는 것이다중요한 점은 Kafk..
Kafka는 “토픽 단위로” 메시지를 받지 않고,항상 “파티션 단위로” 메시지를 기록한다. 즉, 프로듀서가 메시지를 보낼 때마다“이 메시지를 어느 파티션에 쓸 것인가”를 먼저 결정해야 한다.key가 없는 메시지에서 시작되는 round-robin 분배프로듀서가 메시지를 보낼 때 key를 지정하지 않으면,Kafka 프로듀서는 내부적으로 파티셔너(partitioner) 를 통해파티션을 선택한다.이때 기본 동작은 흔히 “round-robin”이라고 불리지만,정확히 말하면 sticky partitioning 기반의 round-robin이다. 실제 동작 방식: Sticky + Round-Robin동작 흐름은 다음과 같다.프로듀서는 전송 가능한 파티션 중 하나를 선택한다일정 시간 동안(또는 배치가 찰 때까지)같은 파..
Kafka에서 파티션 증설은 온라인으로 가능한 작업이다.브로커를 재시작할 필요도 없고, 기존 데이터를 옮기지도 않는다.이 점만 보면 “안전한 작업”처럼 느껴지기 쉽다.하지만 실제 운영에서는, 파티션 증설은 아무 일도 안 일어나는 작업이 아니다.파티션 수가 변경되는 순간, 토픽 메타데이터가 바뀌고Consumer Group은 이를 감지해 리밸런싱을 수행한다.기존 파티션 할당은 모두 해제되고,새 파티션을 포함해 다시 할당되는 과정이 필연적으로 발생한다.이 짧은 구간 동안 컨슈머는 메시지를 소비하지 못하고,모니터링 상에서는 처리량이 급격히 떨어지거나consumer lag이 순간적으로 튀는 모습이 관측된다. 그래서 파티션 증설 이후 “아무 현상도 없었다”고 말하는 건,현실적으로 맞지 않다.리밸런싱, 일시적인 소비..
메시지를 “빠르고, 안정적으로” 소비하는 방법Kafka Consumer에서 대부분의 장애는 “Kafka가 느려서”가 아니라poll 루프, commit, rebalance, timeout의 상호작용을 잘못 이해해서 생긴다.Consumer 설정은 결국 다음 3가지를 어디까지 보장할지에 대한 선택이다.처리 의미론: at-most-once / at-least-once / effectively-once지연과 처리량: latency vs throughput운영 안정성: 리밸런스/재시작/배포 시 흔들림 최소화1. Consumer가 “멈춘 것처럼 보이는” 이유부터운영에서 자주 보는 증상은 이렇다.lag이 갑자기 증가한다Consumer가 죽지 않았는데 처리가 멈춘 것처럼 보인다배포만 하면 리밸런싱이 길게 걸린다대부분은 ..
1. Kafka Producer의 기본 역할 다시 보기Producer는 다음 3가지를 동시에 만족시켜야 한다.안전성 – 메시지가 유실되지 않는가?정합성 – 중복이나 순서 깨짐이 없는가?성능 – 처리량과 지연이 허용 범위인가?Producer 옵션은 이 세 가지를 어디까지 타협할지를 결정한다.2. Producer 설정을 이해하는 큰 틀Producer 옵션은 성격상 4개 그룹으로 나눌 수 있다.내구성 / 정합성재시도 / 중복 방지성능 (배치·압축)트랜잭 션 (선택)3. 내구성과 직결되는 핵심 설정acks acks=all 0 : 응답 기다리지 않음 (유실 가능)1 : leader만 확인 (follower 장애 시 유실 가능)all : ISR 전원 확인운영 환경에서는 사실상 acks=all이 기본 선택이다.min..
1) 이벤트/CDC 토픽 (delete 기반, 운영 표준)일정 기간 재처리 가능디스크 폭주 방지(시간+용량)저유입 파티션에서도 retention 정상 작동(세그먼트 시간 롤링) kafka-topics.sh \ --bootstrap-server localhost:9092 \ --create \ --topic prod.user.state.v1 \ --partitions 6 \ --replication-factor 3 \ --config cleanup.policy=compact \ --config delete.retention.ms=86400000 \ --config min.insync.replicas=2retention.ms=7일retention.bytes=50GB : 시간+용량 이중 안전장치..
클러스터 전체 디스크일일 유입량 × Retention × RF ÷ 압축률 × (1 + 여유율) 브로커 1대당 디스크클러스터 전체 디스크 ÷ 브로커 수 Kafka 장비 산정은 CPU가 아니라 디스크와 네트워크가 기준이다.용량은 peak 기준,여유는 30~50%,브로커는 최소 3대,디스크는 NVMe SSD. num.network.threads=6num.io.threads=12log.segment.bytes=1073741824log.retention.check.interval.ms=300000unclean.leader.election.enable=false 운영 기준 팁Kafka 디스크 사용률 70% 초과는 위험 신호retention 삭제는 즉시 반영되지 않음peak 시점 기준으로 산정해야 함네트워크 용량 산..
https://aws.amazon.com/ko/blogs/tech/remember-s3-tables-part1/ 리멤버앤컴퍼니의 Amazon S3 Tables를 활용한 실시간 분석 워크로드 구축하기 1부: S3 Tables에 CDC 데이리멤버앤컴퍼니 소개 리멤버앤컴퍼니는 대한민국 직장인 500만 명 이상이 사용하는 국내 대표 비즈니스 플랫폼입니다. ‘일하는 사람과 기회를 연결한다’는 미션 아래 개인에게는 명함 관리,aws.amazon.com리멤버는 Databricks가 제공하는 Iceberg Kafka Connect를 사용했습니다. 이 Connector는 2024년 6월 7일 v0.6.19 버전을 마지막으로 Apache Iceberg 프로젝트에 기부되어 더 이상 개발되지 않고 있습니다. Apache Ic..
https://oliveyoung.tech/2024-03-11/msk-cdc-debezium/ 상품데이터 Pipeline을 위한 Debezium MSK Connect | 올리브영 테크블로그MSK Connect Oracle / Aurora CDColiveyoung.tech — binlog 구조부터 snapshot 전략, schema_only 운영까지데이터 플랫폼에서 운영 DB → 데이터 레이크(예: Iceberg) 로 실시간 동기화(CDC)를 구축할 때 가장 널리 쓰이는 기술이 Debezium + Kafka Connect이다.하지만 직접 구축해보면 반드시 부딪히는 의문들이 있다.Debezium은 왜 tasks.max = 1만 지원할까?MySQL binlog는 정확히 어떻게 동작할까?binlog 보존기간 지..
🧱 HBase 핵심 개념 정리NoSQL, Wide-Column Storage, RowKey 설계의 중요성1. HBase란 무엇인가?HBase는 Hadoop 기반의 분산 NoSQL 데이터베이스로,실시간 읽기와 쓰기 연산에 최적화된 Wide-Column Store 구조를 가진 DBMS입니다.특징 설명데이터 모델Google BigTable에서 영감을 받은 구조저장 구조RowKey + Column Family 기반언어SQL 아님 (Get, Put, Scan API 사용)트랜잭션멱등성 보장(O), 다중 Row 트랜잭션(X)Use Case로그, IoT 센서, Clickstream, 시계열 데이터요약: “RowKey를 기준으로 정렬되는 분산 저장소”→ 이 때문에 RowKey 설계 = 성능 설계라고 봐도 된다.2. ..
🧩 ORC vs Parquet: 개요항목ORC (Optimized Row Columnar)Parquet개발 배경Hadoop Hive 팀이 Row Columnar 개선판으로 개발 (2013)Twitter + Cloudera 주도, Dremel 기반 (2013)주요 사용처Hive, Spark, Presto, Iceberg, Flink 등Spark, Presto, Iceberg, Trino, BigQuery 등파일 구조Stripe 단위 (≈ 64MB)로 인덱스 + 데이터 저장Row Group 단위 (≈ 128MB)로 Page 구성메타데이터Footer에 통계 + Index 저장 (세분화된 통계)Footer에 통계 저장 (파일 단위)압축ZLIB, Snappy, LZ4, ZSTD 등GZIP, Snappy, LZ4..
1️⃣ Spark Streaming 이란?Spark Streaming은 대용량 데이터를 실시간(혹은 준실시간) 으로 처리하기 위한 마이크로배치 기반 스트리밍 프레임워크다.Kafka, Socket, Kinesis, File 등에서 데이터를 지속적으로 받아서 RDD 단위로 배치처럼 처리한다.즉, “배치의 안정성과 스트리밍의 실시간성”을 절묘하게 결합한 모델.2️⃣ 동작 원리Spark Streaming의 핵심 개념은 DStream(Discretized Stream) 이다.이는 내부적으로 RDD의 연속(Sequence) 으로 구성되어 있으며,각 배치 간격(batch interval)마다 데이터를 모아 하나의 RDD로 변환한다. Kafka → Receiver → InputDStream → RDD(batchInte..
Spring에서 AOP는 트랜잭션, 로깅, 보안, 성능 모니터링 등공통 로직을 한 곳에서 관리하기 위한 핵심 기술이다.@Transactional도, @Async, @Cacheable도 내부적으로는 AOP 위에서 돌아간다.1️⃣ AOP란?AOP(Aspect Oriented Programming, 관점 지향 프로그래밍) 은비즈니스 로직과 직접 관련은 없지만여러 모듈에서 공통적으로 필요한 기능(부가 기능) 을한 곳에서 관리할 수 있게 해주는 프로그래밍 방식이다.💡 예시로그 출력실행 시간 측정트랜잭션 관리예외 처리인증/인가 (Security)이런 기능을 흩어진 관심사(Cross-Cutting Concern) 라고 부른다.2️⃣ AOP가 필요한 이유기존에는 이런 공통 기능을 각 메서드마다 직접 작성해야 했다.p..
1️⃣ @Transactional의 역할@Transactional은 이름 그대로 트랜잭션 경계를 정의한다.메서드 실행 전후로 Spring이 자동으로 다음을 수행한다.트랜잭션 시작 (connection.setAutoCommit(false))비즈니스 로직 실행정상 종료 시 → Commit예외 발생 시 → Rollback즉, 개발자는 “트랜잭션 경계를 직접 관리하지 않고”,선언적 트랜잭션(declarative transaction) 방식으로 처리할 수 있다.2️⃣ 내부 동작 구조 — AOP Proxy 기반@Transactional은 단순한 어노테이션이 아니다.스프링은 이를 인식해 AOP Proxy 객체를 생성한다.동작 순서스프링이 Bean을 생성할 때, @Transactional이 붙은 클래스를 스캔한다.해당..
처음엔 잘 작동하던 코드가 데이터가 많아지면서 갑자기 느려지기 시작한다면,그 배경엔 종종 N+1 쿼리가 숨어 있다.1️⃣ N+1 문제란?간단히 말해,한 번의 조회로 충분한 데이터를 가져오지 못하고,연관된 데이터를 가져오느라 추가 쿼리가 N번 더 실행되는 문제다.예를 들어 이런 코드가 있다고 해보자. List members = em.createQuery("select m from Member m", Member.class).getResultList();for (Member member : members) { System.out.println(member.getTeam().getName());}이 코드는 언뜻 보면 문제가 없어 보이지만, 실제 실행되는 SQL을 보면 이렇다.select * from me..
🎯 콘텐츠 딜리버리의 데이터 특성콘텐츠 딜리버리 서비스는 단순한 캐시 서버가 아니다.사용자별 콘텐츠 노출 상태, 시청 이력, 추천 지표 등 상태성 메타데이터를 대규모로 영속 저장해야 한다.이 데이터들은 다음과 같은 특성을 가진다.하루에도 수억 건 이상 누적되는 로그성 데이터user_id + content_id 또는 category + time 기반의 Range Scan 요청 다수랜덤 읽기 + 순차 스캔이 섞인 패턴장애 시에도 데이터 복구가 가능한 영속성 필수즉, 단순히 빠르게 한두 개 키를 조회하는 캐시 시스템이 아니라대용량 상태 데이터를 안전하게 저장하고 조회해야 하는 분산 스토리지가 필요했다.⚙️ Redis vs HBase 비교구분RedisHBase데이터 구조단순 Key-ValueWide-Colum..
1️⃣ Spark Driver & Executor 구조 이해Spark 애플리케이션은 크게 Driver와 Executor로 구성된다.구성요소역할Driver전체 DAG를 구성하고, Task를 스케줄링하고, 결과를 수집함. (Application의 뇌)Executor실제 Task를 실행하는 워커 프로세스. 여러 개의 스레드(Core)로 병렬 수행함.CoreExecutor 내에서 동시에 실행 가능한 Task의 개수.MemoryExecutor가 데이터를 캐싱하거나, 셔플 버퍼를 유지하거나, 사용자 객체를 저장하는 공간.즉, Spark는 **“Driver가 계획을 세우고, Executor들이 나눠서 일하는 구조”**다.“Spark는 마스터-워커 구조로, Driver가 스케줄링을 담당하고 Executor가 병렬 Ta..
— 데이터가 절대 유실되지 않게 만드는 최소 복제 전략Kafka는 “분산 로그 시스템”이다.즉, 모든 데이터를 여러 브로커(broker)에 복제(replication) 해서 보관한다.이때 복제본이 몇 개나 유지될지를 정하는 설정이 바로 replication.factor 다.1️⃣ 기본 개념replication.factor = 각 파티션이 몇 개의 브로커에 복제되어 저장될지 결정하는 값.예를 들어, replication.factor=3 이면 각 파티션의 로그가3개의 서로 다른 브로커에 동시에 저장된다.1개는 리더(Leader)나머지 2개는 팔로워(Follower)이 세 개가 모두 같은 데이터를 유지하면서 동기화된다.2️⃣ 구조 예시예: 토픽 orders, 파티션 1개, replication.factor=3..
— 속도 vs 안정성 어디까지 가져갈 것인가Kafka 프로듀서 설정 중에 제일 많이 물어보는 게 이거다.“acks는 0으로 하면 빨라지고, all로 하면 안전하다면서요? 그럼 1은 뭐죠?”설명 자체는 쉽지만, 언제 어떤 걸 써야 하는지는 실제 워크로드를 알아야 결정할 수 있다.이 글에서는 acks가 의미하는 걸 브로커 관점에서 다시 정리하고,실무에서 많이 쓰는 패턴까지 정리해본다.1. acks가 하는 일acks 는 “프로듀서가 이 메시지가 진짜로 써졌다고 믿기 전에, 브로커에게서 어느 수준까지 확인을 받겠다” 는 약속이다.즉, 누가 “쓰기 성공”을 선언하느냐의 레벨을 고르는 거다.낮은 값 → 빠름, 대신 유실 가능높은 값 → 느려짐, 대신 안전2. acks=0 acks=0 동작프로듀서가 브로커 응답을 아..
— 데이터 저장 방식에 따라 쿼리 성능이 이렇게 달라진다데이터 포맷이나 스토리지를 이야기할 때 자주 나오는 말이 있다.“이건 row 기반이고, 저건 column 기반이에요.”딱 들으면 뭔가 어려워 보이지만, 핵심은 간단하다.데이터를 “어떻게 묶어서 디스크에 저장하느냐”의 차이다.이 글에서는 그 구조적 차이와,왜 분석용 데이터는 대부분 column 기반으로 가는지를 살펴본다.1️⃣ 개념: “데이터를 한 줄씩 저장할까, 한 컬럼씩 저장할까”Row-based (행 지향)데이터를 “한 행(row)” 단위로 저장한다.즉, 한 사람(레코드)의 모든 필드가 한 번에 붙어서 저장된다. Row1: [id=1, name='Kim', age=30, city='Seoul'] Row2: [id=2, name='Lee', age..
서비스가 잘 되면 트래픽이 늘고, 트래픽이 늘면 제일 먼저 비명을 지르는 애가 보통 Kafka 브로커입니다.그런데 막상 까보면 브로커가 “못 받는” 게 아니라, 프로듀서가 “너무 자주, 너무 잘게” 보내서 그런 경우가 많습니다.그래서 이 글의 포인트는 단순합니다.“메시지 양이 많아졌을 때는 한 번에 많이, 덜 자주 보내도록 프로듀서를 바꿔라.”그걸 가능하게 하는 게 프로듀서 옵션 튜닝입니다.1. 먼저 구조부터 이해하기Kafka 브로커가 힘들어지는 패턴은 보통 이렇습니다.프로듀서가 이벤트를 한 건씩 바로바로 보냄 →브로커는 메시지 내용보다 “요청 수” 때문에 바빠짐 →리더 파티션을 가진 브로커 몇 대에 부하 몰림 →레이턴시가 늘고, 프로듀서 쪽 retry가 늘면서 더 많은 요청이 들어옴 →악순환즉, “메시..
1️⃣ 스키마 진화(Avro Schema Evolution)란?데이터가 쌓이는 동안, 서비스는 끊임없이 변한다.새로운 필드가 생기고필드명이 바뀌고타입이 변하고더 이상 쓰지 않는 값이 생긴다문제는 이런 변화가 있을 때 기존 데이터가 깨지면 안 된다는 것이다.Avro는 바로 이 부분을 **스키마 호환성(Compatibility)**으로 해결한다.즉, 새로운 스키마로도 예전 데이터를 읽을 수 있게 하거나,예전 스키마로도 새 데이터를 읽을 수 있게 만든다.2️⃣ 호환성의 세 가지 개념구분설명비유Backward Compatibility새 스키마로 옛 데이터를 읽을 수 있음“새 버전의 코드가 옛날 JSON을 읽을 수 있다”Forward Compatibility옛 스키마로 새 데이터를 읽을 수 있음“옛날 코드가 새 ..
- Total
- 181,750
- Today
- 6
- Yesterday
- 15
- 메디파크 내과 전문의 의학박사 김영수
- 테슬라 리퍼럴 코드 혜택
- 인스타그램
- 테슬라 레퍼럴 코드 확인
- Bot
- 어떻게 능력을 보여줄 것인가?
- 김달
- follower
- 테슬라
- 테슬라 레퍼럴
- Kluge
- 개리마커스
- 테슬라 리퍼럴 코드
- 테슬라 레퍼럴 적용 확인
- 할인
- 연애학개론
- 클루지
- 유투브
- 테슬라 추천
- 테슬라 리퍼럴 코드 생성
- COUNT
- 테슬라 크레딧 사용
- 팔로워 수 세기
- wlw
- 모델y
- 레퍼럴
- 책그림
- 모델 Y 레퍼럴
