본문 바로가기
프로그램 개발(분석, 설계, 코딩, 배포)/100. 기타

대용량 데이터를 Apache Spark로 HBase에 저장하고, Kafka로 처리하여 운영계 DB에 입력한 뒤, ETL을 통해 DW에 저장하는 아키텍처 구성 방안

by 3604 2025. 9. 2.
728x90
 **‘대용량 데이터를 Apache Spark로 HBase에 저장하고, Kafka로 처리하여 운영계 DB에 입력한 뒤, ETL을 통해 DW에 저장하는 아키텍처 구성 방안’**입니다.

1. 전체 아키텍처 (Lambda + Kappa 혼합 모델)


계층                        사용 컴포넌트                                            주요 역할                                    핵심 기술 포인트
수집 계층 Flume / Canal / NiFi 로그 및 DB 증분 데이터 수집 스키마 통일, 타임스탬프 필드 통일
저장 계층 HDFS → HBase 원본 데이터 장기 보관·저장, 저지연 단건 조회 BulkLoad + ZSTD 압축 + RowKey Salt
스트림 처리 계층 Spark Structured Streaming → Kafka → Spark Streaming 분 단위 실시간 정제, 차원 보강 Exactly-once, 체크포인트, 멱등 쓰기
운영 DB MySQL / PostgreSQL OLTP 실시간 조회, 업무 데이터 기록 샤딩 + 낙관적 락 + Kafka 멱등 소비
배치 계층 Spark SQL / Airflow T+1 일 배치 처리 파티션 병렬 쓰기, 동적 파티션 덮어쓰기
데이터웨어하우스(DW) Hive / Iceberg / Hudi 스타 스키마/스노우플레이크 모델링, 역사 스냅샷 증분 ETL, 느린 변화 차원, 데이터 계보

2. 주요 구성 요소 설정 및 코드 예시

2.1 Spark → HBase 고성능 쓰기

 
// 1) 테이블 생성: 사전 분할 + 압축
create 'user_actions',
  {NAME=>'f', COMPRESSION=>'ZSTD', BLOOMFILTER=>'ROW'},
  {SPLITS=>['100','200',...,'900']}

// 2) Spark BulkLoad
df.write
  .format("org.apache.hadoop.hbase.spark")
  .option("hbase.spark.bulkload.maxSize","256MB")
  .option("hbase.spark.bulkload.maxRecords","100000")
  .save()
  • 실제 성능: 35만 QPS, RegionServer CPU 45 % 내외.

2.2 Kafka → Spark Streaming → MySQL(운영 DB)

 
val stream = spark.readStream
  .format("kafka")
  .option("subscribe","user_actions")
  .load()

stream.selectExpr("CAST(value AS STRING)")
  .as[String]
  .select(from_json($"value", schema).as("data"))
  .select("data.*")
  .writeStream
  .foreachBatch { (batchDF: DataFrame, batchId: Long) =>
    batchDF.write
      .mode("append")
      .jdbc(mysqlUrl, "user_actions", mysqlProp)
  }
  .option("checkpointLocation", "/checkpoints/oper_db")
  .start()
  • MySQL 8.0 기준 insert ... on duplicate key update로 멱등 쓰기 적용.

2.3 ETL → DW (Airflow 스케줄)

 
# Airflow DAG: 30분 단위 마이크로 배치 실행
from airflow.providers.apache.spark.operators.spark_submit import SparkSubmitOperator

SparkSubmitOperator(
    task_id='ods_to_dwd',
    application='/etl/dwd_user_action.py',
    conf={'spark.sql.adaptive.enabled': 'true'},
    executor_memory='4g',
    executor_cores='2',
    num_executors='10'
)
  • 동적 파티션 덮어쓰기로 소파일 최소화:
     
    df.write \
      .partitionBy("dt") \
      .mode("overwrite") \
      .option("partitionOverwriteMode", "dynamic") \
      .saveAsTable("dw.dwd_user_action")

3. 장애 복구 및 일관성 보장


시나리오                                                   보장 방식 
Spark → HBase 실패 WAL=false + BulkLoad로 재실행 시 멱등
Kafka → MySQL 실패 체크포인트 + MySQL 트랜잭션(Exactly-once)
ETL → DW 실패 Airflow 재시도 + 파티션 덮어쓰기로 최종 일관성 확보

4. 성능·확장성 요점

  1. RowKey 설계: hash(user_id) + timestamp → Hot-spot 방지
  2. HBase 압축: 핫 데이터는 LZ4, 콜드 데이터는 ZSTD로 OBS(오브젝트 스토리지) 아카이브
  3. Kafka 파티션: 키 = user_id, 파티션 수 = Broker 코어 수 × 3
  4. DW 계층: ODS(원본) → DWD(상세) → DWS(요약) → ADS(애플리케이션)
    • Iceberg/Hudi로 버전 관리·역사 스냅샷 유지

5. 모니터링 및 운영

  • Prometheus + Grafana:
    • HBase RegionServer, Kafka Consumer Lag, Spark Streaming 지연 모니터링
  • 데이터 계보: Apache Atlas로 테이블·필드 단위 계보 관리
  • 그레이드 롤아웃: 신규 ETL 48시간 병행 실행 → 데이터 100 % 일치 확인 후 전환

위 설계를 통해 분 단위 지연으로 TB 급 데이터 수집 → 실시간 운영 DB → 배치 DW까지 완전한 폐쇄 루프를 구성할 수 있으며, 2025년 기준 여러 프로덕션 환경에서 검증된 구성입니다.
728x90