RDB 와 Hadoop 의 차이
Rdb는 공유 스토리지를 사용하기 때문에 데이터 저장량이 늘어나고 공유스토리지 연산 컴퓨팅 리소스가 늘어나면 일정 수준 이상으로 성능을 올리면 i/o가 문제가 생기는데 하둡은 그렇지 않은 이유
공유 스토리지 : 서버가 데이터를 찾기 위해 디비 서버에 직접 접근하는 것 → 중앙 저장소, 모든 I/O 요청이 공유 스토리지로 집중되는 구조
- 공유 스토리지는 데이터를 한 곳에 저장하니 트랜잭션 관리가 쉽다.
- 하지만 요청이 한 서버로 몰리기 때문에 Disk I/O 가 병목될 수 있으며 고가용성을 위해 스토리지 레벨 또는 로그로 복제한다.
하둡은 분산 로컬 스토리지
하둡의 저장 구조는 HDFS (Hadoop Distributed File System)
구성 요소 | 설명 |
NameNode | 메타데이터 관리 (파일 이름, 블록 위치 등) |
DataNode | 실제 데이터 저장 (각 노드의 로컬 디스크) |
블록 분산 저장 | 하나의 파일을 여러 블록으로 나누고, 서로 다른 노드에 분산 저장 |
복제(replication) | 기본적으로 각 블록은 3개 복제 (고가용성 보장) |
- 분산 저장 + 분산 연산
- 저장, 계산 전부 각 노드의 로컬 디스크를 사용한다. → 중앙 스토리지 병목 없음
- 데이터가 있는 노드에서 연산 실행
- 연산이 거창한 게 아니라 그냥 데이터가 있는 노드에서 조회한다고 보면 된다. 다른 노드에서 가져와서 조회한다가 아닌 가지고있는 노드에서 직접 조회한다는 것임
- 스케일 아웃이 매우 쉽다
- 노드를 추가하면 저장량도 연산력도 비례적으로 증가
엥 그럼 RDB 는 어떻게 스케일 아웃함?
- 샤딩
- 데이터를 물리적으로 다른 서버에 분산 저장
- user_id % 3 == 0 → DB1
- user_id % 3 == 1 → DB2
- user_id % 3 == 2 → DB3
- 운영 복잡도 매우 증가 ㄷㄷ → 실제로 잘 사용하나
- 데이터를 물리적으로 다른 서버에 분산 저장
- Read-Write 분리
- 읽기는 slave 쓰기는 master
- 로그 기반으로 복제되기도 함
- 완전한 수평확장은 아님
그럼 하둡은???
처음부터 데이터를 분산 저장하도록 설계
- 데이터를 작은 블록(기본 128MB) 로 나눈다.
- 여러 노드에 분산해 저장한다.
- 복제까지 자동으로 관리한다. (기본 3개)
- 연산(조회)도 그 노드에서 바로 수행 → 데이터 이동 최소화
- 연산은 Spark, MapReduce 같은 애들이 직접 데이터 있는 노드에서 수행
연산을 그 노드에서 수행한다는 게 뭔말임???
Spark 기준
- Spark Driver가 네임노드에서 파일 블록 위치(=DataNode)를 알아냄
- 각 Executor(Task)가 그 데이터가 위치한 노드에 자동 배치됨
- 그 Executor는 로컬 디스크에서 .parquet 파일을 직접 읽고, filter, map, groupby 같은 연산을 그 자리에서 수행함
- 필요한 결과만 최소로 네트워크로 전송
예시
val df = spark.read.parquet("hdfs:///warehouse/user_log/")
val filtered = df.filter($"user_id" === 12345)
이 코드를 Spark가 처리한다면
- user_log 데이터는 worker-1, worker-2, worker-3에 각각 나뉘어 저장
- Spark는 각 worker 노드에 Task를 분산함
- 예를 들어 user_id=12345가 worker-2의 .parquet 에 있으면
- 그 filter는 worker-2의 Executor가 직접 수행함 → data locality
- 다른 노드로 데이터를 옮기지 않아도 됨
- 그 필터링된 결과만 나중에 Spark Driver나 앱으로 전송됨
구분 | 설명 |
❌ “연산을 마스터 노드에서 수행한다” | 데이터를 전부 가져와서 마스터에서 계산 → 비효율 |
✅ “연산을 데이터 노드에서 수행한다” | 데이터를 보관 중인 노드에서 계산까지 수행 → 네트워크 부하 ↓ |
📌 핵심 | 필터링, 집계, 변환 등을 가진 곳에서 직접 하고, 최소한의 데이터만 전송함 |
→ 그냥 그 데이터 노드에서 직접 연산을 수행한다는 말이 맞쬬?
Hive metastore
RDBMS 테이블 형식으로 파일의 메타데이터를 저장하자! → 회사에선 Postgres 를 쓴다네
- Hive가 사용하는 “카탈로그” 같은 역할
- Spark, Trino 등도 이 Hive Metastore를 조회해서 “어떤 테이블이 있고”, “컬럼이 뭐고”, “어디 저장돼있고”, “무슨 포맷이야?” 를 알아냄
어떤 형식으로 저장되나염?
RDB 테이블 형식으로 다음과 가튼 메타데이터들 저장
테이블 이름 | 내용 |
DBS | Hive 상의 Database들 |
TBLS | 각 Database 안의 Table 목록 |
COLUMNS_V2 | 테이블/파티션의 컬럼 정보 |
SDS | 테이블의 물리적 저장 포맷, 파일 경로 |
SKEWED_COL_NAMES, PARTITIONS 등 | 파티션 정보 |
SERDES, STORAGE_DESCRIPTIONS | 입력/출력 포맷, 포맷 처리기 |
BUCKETING_COLS, SORT_COLS | 버킷 컬럼, 정렬 등 |
실제 데이터를 저장하는 것은 아님
실제 데이터는 HDFS 등에 저장되는데, hive metastore 는 이 테이블이 “어느 위치”에 있고 “어떤 구성”을 하고 있는지만 알 수 있음.
- 테이블 구조
- 컬럼
- 파티션
- 저장 포맷
- 파일 경로 등
그럼 누가 사용함?????
회사에서 쓰는거 기준으로 설명
- Spark SQL
- Trino
- Trino에 쿼리했을 때 테이블 구조
- Iceberg catalog ( Hive Catalog)
- 아이스버그를 통해 하둡에 저장된 실제 데이터를 관리한다.
괜찮은 아키텍쳐
Iceberg hive catalog
- 실제 데이터는 HDFS 에 저장되어 있고 아이스버그 테이블로 관리된다. 메타데이터는 하이브에 저장한다.
- Spark , Trino 같은 시스템들이 Iceberg 테이블을 참고하여 데이터를 조회하는 등등
어떻게 구성 됨?
로그를 저장한다고 가정하자
- Iceberg 테이블 생성
-- Spark 또는 Trino에서 Iceberg 테이블 생성
CREATE TABLE db.user_log (
user_id INT,
log_time TIMESTAMP,
dt STRING
)
PARTITIONED BY (dt)
STORED AS ICEBERG
LOCATION 'hdfs:///warehouse/user_log'
이 때
- 테이블 구조 정보 → Hive metastore 저장 : 테이블명, 컬럼, 파티션 정보
- Iceberg metadata files → HDFS : JSON 형식으로 Iceberg 전용
- 실제 데이터 파일 → HDFS : Parquet 등으로 저장.
[1] Hive Metastore (외부 카탈로그)
└── 테이블 이름, 위치, 스냅샷 참조 등
[2] Iceberg 메타데이터 파일
└── manifest.json, snapshot.json 등 (버전 관리)
[3] 실제 데이터 파일
└── Parquet, ORC 파일들 (HDFS, S3 등에 저장)
구조의 장점
장점 | 설명 |
💾 메타데이터 독립성 | Iceberg는 자체적인 메타데이터 파일(manifest, snapshot)을 통해 성능 높임 |
🔁 스냅샷 관리 | Iceberg는 Append-only 방식 + 스냅샷 기반 → Rollback, Time-travel 가능 |
🚀 쿼리 최적화 | 파일 단위로 filter-pushdown, schema evolution, hidden partitioning 가능 |
🌐 Hive Metastore 연동 | 기존 Hive 기반 플랫폼(Trino, Spark, Airflow 등)이 그대로 연동됨 |
만약 Spark 로 접근한다고 가정하면..
- spark 가 hive metastore 에서 테이블 위치를 알아냄.
- 위치에 있는 Iceberg metadata JSON 파일을 읽음.
- 어떤 시점의 snapshot 을 사용할 것인가 정하기. (어떤 시점의 데이터를 사용할 것인가?)
- 아이스버그는 append only 로, 쓰기가 일어날 때마다 새로운 snapshot 생성 → 과거의 특정 snapshot 을 가져와 time travel 가능.
- 그 스냅샷에 연결된 manifest 파일을 열고 그 안에 있는 parquet 목록 파악
- 그 파일들을 spark 가 병렬로 읽는다.
Spark 는 어떻게 하이브 메타스토어에 접근이 가능할까? → HiveCatalog
spark.sql.catalog.my_catalog=org.apache.iceberg.spark.SparkCatalog
spark.sql.catalog.my_catalog.type=hive
spark.sql.catalog.my_catalog.uri=thrift://hive-metastore:9083
이렇게 설정할 경우, Spark 가 Iceberg 작업을 할 때
- Iceberg API 로 메타데이터 쓰기
- Hive metastore 에도 동시에 테이블 등록
HDFS 구조
/warehouse/user_log/
├── data/
│ ├── 00000-abc.parquet
│ └── 00001-def.parquet
├── metadata/
│ ├── v1.metadata.json
│ ├── v2.metadata.json
│ └── snapshots/
└── hive_metastore_entry (등록만 되어 있음, 실파일 없음)
- hive_metastore_entry <<< 이건 실존하는 파일은 아님
- Hive Metastore에 “이 테이블은 이 위치(hdfs:///warehouse/user_log/)에 있다”는 등록 정보만 있다 는 뜻
- Hive Metastore는 실제 데이터를 저장하지 않고 → 테이블 이름 / 스키마 / 저장 위치 등의 메타 정보만 가지고 있음
- Hive Metastore가 이 파일을 보고 아 여기에 파일이 있구나 표시하는 용도
요약
- 스파크나 트리노에 쿼리로 데이터를 요청하면…
- Spark/Trino에서 Iceberg 테이블에 쿼리 실행 시작
- 일단 하이브와 통신하여 ‘데이터의 메타데이터를 저장 중인 아이스버그 테이블의 위치’를 알아내고
- Hive Metastore에서 Iceberg 테이블의 ‘물리적 경로’를 얻어옴.
- (예: hdfs:///warehouse/db/user_log/)
- 테이블의 위치를 알아내면 아이스버그 테이블에 들어가 메타데이터를 확인하여 실제 데이터의 위치를 확인 후
- Iceberg의 metadata/ 디렉터리에 있는 JSON 파일들 (snapshot, manifest)을 읽고 그 안에서 어떤 .parquet 파일이 존재하는지 확인함
- 스파크가 실제 하둡 경로로 들어가 데이터를 읽어온다
- 그 파일 목록을 가지고 Spark가 병렬로 HDFS에서 데이터를 읽어옴
- Spark는 파일을 읽는 쪽도 분산돼 있고, Iceberg는 각 파티션/파일을 정교하게 추적하고 있어서 성능도 좋음
- 트리노라면 트리노 worker 가 읽음.
728x90
'개발공부 개발새발 > Hadoop' 카테고리의 다른 글
Hadoop ) 로컬에 hadoop 3.2.2 설치하기 (3) | 2025.06.25 |
---|