- 이전 회사에서 집계 기능 개발할 때, RDS 만으로는 무거운 배치성 집계 쿼리를 처리하기에 한계가 있었다
꽤 무거운 쿼리였어서 Read Replica 를 사용함에도 운영 DB 에서 돌리면 병목이 발생하고 CPU 사용도 많고, 인덱스 구조상 대량집계에는 최적화되어있지 않는 등
그래서 그때 한참 하둡 이런거 알아봤었는데 그때는 데이터 규모와 운영 복잡도를 고려해서 분산처리기반 아키텍처는 과하다고 판단하여 보류했었다
- 정리하면 당시에 원했던바는 분석이나 집계를 운영 DB 에서 하고싶지 않았고, 그래서 찾아보았던게 운영과 분석 분리 및 선집계 아키텍처 등이었다
지금 회사에서는 데이터팀이 따로 있긴하지만 Databricks 를 이미 사용하고 있어서 그때 공부했던것도 되살리며 겸사겸사 간단 TIL 을 적으려한다
OLTP(운영 DB) vs OLAP(분석/집계)
서비스에는 두 종류의 데이터 처리가 있음
- OLTP (Online Transaction Processing) : 서비스 운영용
- 목표 : 단건 트랜잭션 안정성, 응답 속도 최우선
- ex) 단건 조회/쓰기 중심
- 구조 : 보통 Row 기반, 트랜잭션 중심
- ex) Amazon RDS
- 목표 : 단건 트랜잭션 안정성, 응답 속도 최우선
- OLAP (Online Analytical Processing) : 분석/집계용
- 목표 : 대량 데이터 집계와 분석 효율
- ex) 일별 매출 통계, 랭킹 산출, 대량 집계 파이프라인
- 구조 : Columnar 기반, 분산 클러스터 병렬 처리
- ex) Amazon Redshift, Google BigQuery, Snowflake
- 목표 : 대량 데이터 집계와 분석 효율
OLTP 와 OLAP 는 설계 목적과 처리 방식이 근본적으로 다름
데이터 규모와 요구사항에 따라 다르지만, 운영 DB에 무거운 분석 쿼리를 올리면 병목이 발생하므로 일정 규모 이상에서는 운영과 분석을 분리하는 것이 일반적임
분석 데이터 저장 방식
그럼 운영과 분리하고나면 분석 데이터는 어디에 저장하지?
분석 스토리지는 크게 세 가지 아키텍처로 발전해왔음 Data Warehouse → Data Lake → Lakehouse
DW (Data Warehouse)
- 분석 전용 DB
- 정제된 데이터 저장
- SQL 기반 집계 최적화
- ex) Amazon Redshift, Google BigQuery, Snowflake
Data Lake
- S3 같은 오브젝트 스토리지에 Parquet 같은 파일로 저장
- 원본 포함 대용량 데이터 저장
- 저비용, 유연성 높음
하지만 기본적으로는 파일 저장소일 뿐
트랜잭션 없고, 스키마 강제 안 되고, 쿼리 성능 보장 안 됨 = DB 기능은 약하다
- 💡 참고) 하둡은?
- 하둡이 딱 Data Lake 개념 자체는 아닌데 Data Lake의 원조 구현체 정도로 보면 됨
- HDFS(분산 저장) + MapReduce(분산 처리) 조합이엇는데 → 너무 복잡하고 느림 → S3 + Spark로 대체됨
→ 근데 파일 저장소라 DB 기능 약함 → Lakehouse 등장
Lakehouse
여기서 등장하는 개념이 Lakehouse
- 파일 기반 저장
- DB 처럼 테이블 관리
- ACID 지원 (파일 기반인데도 트랜잭션이 보장된다는 게 핵심), SQL 가능
즉 Warehouse의 관리 기능(트랜잭션/쿼리 최적화) + Data Lake의 유연성(원시 데이터 저장) 을 결합한 구조
- ex) Databricks (Delta Lake - Lakehouse 아키텍처를 실제로 구현한 Databricks의 기술)
- S3에 Parquet 파일이 쌓여있다고 치면 그냥 파일이라 이 파일 언제 바뀌었는지, 트랜잭션 실패하면 어떻게 롤백하지, 어떤 파일이 어떤 테이블인지 같은 걸 알 수가 없음
Delta Lake가 그걸 관리해주는 레이어임 그래서 똑같은 S3 Parquet 파일인데 Delta Lake 있으면 DB처럼 쓸 수 있음
= S3 Parquet 파일 위에서 테이블로 관리, 트랜잭션 로그, 롤백을 담당하는 레이어- 타임 트래블(Time Travel) 가능 -> 과거 상태 조회 가능
- MERGE / UPSERT 가능 -> 실시간 데이터 반영 용이
- S3에 Parquet 파일이 쌓여있다고 치면 그냥 파일이라 이 파일 언제 바뀌었는지, 트랜잭션 실패하면 어떻게 롤백하지, 어떤 파일이 어떤 테이블인지 같은 걸 알 수가 없음
Spark 분산 처리 원리
그럼 이렇게 쌓인 대용량 데이터를 어떻게 빠르게 계산하지?
여기서 Apache Spark가 등장함
Spark 는 대용량 데이터를 여러 서버에서 동시에 계산하는 엔진
Databricks는 Spark를 기반으로 동작함
Spark는 하둡의 MapReduce를 대체한 분산 처리 엔진으로, 훨씬 빠르고 쓰기 쉬움
개념은 단순함
- 데이터를 여러 조각으로 나눈다
- 여러 머신에서 병렬 처리한다
- 결과를 합친다
- ex) 10억 건 집계를 한다면
- RDS → 한 서버가 혼자 계산
- Spark → 여러 서버가 나눠 계산 이게 분산 처리
선집계 아키텍처
그러면 Spark로 계산한 결과를 서비스에 어떻게 연결하지?
Spark로 집계한다고 해도 매 요청마다 10억 건을 계산하면 여전히 무거움
그래서 실무에서는 계산 자체를 미리 해둠
- 원본 데이터는 분석 스토리지에 저장
- 배치 또는 스트리밍으로 집계 테이블 미리 생성
- 서비스는 그 집계 테이블만 조회
- 조회가 잦으면 Redis 캐시까지 적용
= 요청이 들어왔을 때 계산하는 게 아니라 이미 계산된 결과를 그냥 읽어옴 => 선집계 아키텍처
- 장점
- 서비스 응답 속도 빠름
- 운영 DB 부담 최소화
- 대량 집계에도 안정적
근데 databricks 에서 데이터 조회나 쿼리 시에 테이블처럼 보여서 RDS 와의 차이가 겉으로는 느껴지지 않았다
똑같이 DB 처럼 쿼리 날리는데 알고보면 내부에서 파일로 저장된 데이터를 Delta Lake가 테이블처럼 보여주고, Spark가 그걸 읽어서 계산해주는 구조
= DB는 아닌데 파일 기반 위에 DB처럼 추상화한 것
이전 회사에서 고민했던 운영 DB에서 집계를 빼고 싶다는 문제를 지금 회사에서는 이런 아키텍처로 해결해두고 있었던 것
RDS 와 차이를 요약하자면 데이터를 로우기반이 아닌 파일기반으로 저장하고 여러서버로 병렬처리한다 정도로만 알고있으면 될듯