본문 바로가기

카테고리 없음

스파크 RDD(메타코드, 데이터 엔지니어링)

반응형

스파크 RDD (Resilient Distributed Dataset)란?

Apache Spark는 대규모 데이터 처리를 위한 강력한 분산 컴퓨팅 플랫폼입니다. 그 핵심 구성 요소 중 하나인 **RDD (Resilient Distributed Dataset)**는 스파크의 기본 데이터 처리 단위로, 분산 환경에서 데이터를 효율적으로 처리할 수 있도록 설계되었습니다. 이번 포스팅에서는 스파크 RDD의 개념, 특징, 장점 및 주요 API에 대해 살펴보겠습니다.


1. RDD란 무엇인가?

RDD (Resilient Distributed Dataset)는 불변(Immutable)하고 분산(Distributed)된 데이터셋으로, Spark에서 데이터를 표현하는 기본 단위입니다. RDD는 Spark의 가장 기초적인 데이터 추상화이며, 대규모 데이터를 분산 환경에서 처리할 수 있는 기초를 제공합니다.

주요 특징

  1. Resilient (복원력):
    • 데이터가 손실되더라도, RDD는 복구 메커니즘(혈통 정보, Lineage)을 통해 원래 데이터를 다시 생성할 수 있습니다.
  2. Distributed (분산):
    • 데이터는 여러 노드에 분산 저장됩니다. 이로 인해 대규모 데이터를 병렬로 처리할 수 있습니다.
  3. Immutable (불변):
    • RDD는 생성 후 변경할 수 없습니다. 대신, 기존 RDD에서 새로운 RDD를 만들어내는 방식으로 데이터를 변형합니다.
  4. Lazy Evaluation (지연 실행):
    • RDD 연산은 즉시 실행되지 않고, 액션(Action)이 호출될 때만 실행됩니다. 이는 성능 최적화를 가능하게 합니다.

2. RDD의 장점

  • 장애 복구: RDD는 혈통(Lineage) 정보를 통해 데이터를 복구할 수 있어 장애에 강합니다.
  • 병렬 처리: 클러스터 내 여러 노드에 데이터를 분산하여 병렬 처리 속도를 극대화합니다.
  • 유연성: 다양한 데이터 소스 (HDFS, Cassandra, HBase 등)와 데이터 유형을 지원합니다.
  • 효율성: 지연 실행과 캐싱을 통해 리소스 사용을 최적화합니다.

3. RDD 생성 방법

RDD는 주로 두 가지 방식으로 생성됩니다:

  1. 외부 데이터 소스에서 생성
    • HDFS, S3, HBase 등의 외부 저장소에서 데이터를 읽어 RDD를 생성할 수 있습니다.
  2. 컬렉션에서 생성
    • 로컬 Scala, Python, Java 컬렉션을 SparkContext의 parallelize 메서드를 사용해 RDD로 변환할 수 있습니다.

예제

python
코드 복사
from pyspark import SparkContext # SparkContext 생성 sc = SparkContext("local", "RDD Example") # 1. 컬렉션에서 RDD 생성 data = [1, 2, 3, 4, 5] rdd = sc.parallelize(data) # 2. 외부 데이터 소스에서 RDD 생성 text_rdd = sc.textFile("hdfs://path/to/file.txt")

4. RDD의 주요 연산 (Transformations & Actions)

RDD 연산은 크게 두 가지로 나뉩니다:

4.1 Transformations (변환 연산)

Transformations는 기존 RDD에서 새로운 RDD를 생성합니다. 지연 실행되며, 결과는 Action이 호출될 때만 평가됩니다.

Transformation설명예제

map 각 요소에 함수를 적용하여 새로운 RDD 생성 rdd.map(lambda x: x * 2)
filter 조건에 맞는 요소만 포함하는 RDD 생성 rdd.filter(lambda x: x % 2 == 0)
flatMap 요소를 개별 요소로 변환 rdd.flatMap(lambda x: (x, x**2))
distinct 중복 제거 rdd.distinct()
join 두 RDD를 조인 rdd1.join(rdd2)

4.2 Actions (액션 연산)

Actions는 RDD의 결과를 반환하거나 저장합니다. 즉시 실행됩니다.

Action설명예제

collect 모든 데이터를 드라이버로 반환 rdd.collect()
count 요소의 개수를 반환 rdd.count()
take 상위 n개 요소 반환 rdd.take(3)
saveAsTextFile RDD를 텍스트 파일로 저장 rdd.saveAsTextFile("output")
reduce 병합 연산 수행 rdd.reduce(lambda x, y: x + y)

5. RDD의 혈통 (Lineage)과 캐싱

  1. 혈통(Lineage): RDD는 연산 이력을 추적하여 장애 시 데이터를 복구할 수 있습니다. 이는 Spark UI에서도 시각적으로 확인할 수 있습니다.
    • 위 예제에서 filtered_rdd는 혈통 정보로 rdd -> map -> filter 과정을 유지합니다.
  2. python
    코드 복사
    rdd = sc.parallelize([1, 2, 3, 4]) mapped_rdd = rdd.map(lambda x: x * 2) filtered_rdd = mapped_rdd.filter(lambda x: x > 5)
  3. 캐싱(Caching): 반복적으로 사용되는 RDD는 cache()나 persist()를 사용해 메모리에 저장할 수 있습니다. 이는 성능을 크게 향상시킵니다.
  4. python
    코드 복사
    cached_rdd = rdd.cache()

6. RDD vs DataFrame vs Dataset

Spark에서는 RDD 외에도 DataFrameDataset을 제공합니다. 각각의 장단점을 이해하고 적절한 도구를 선택하는 것이 중요합니다.

특성RDDDataFrameDataset

타입 타입 불명 Row 기반 타입 지정 가능
API 함수형/객체 지향 SQL과 유사한 API 제공 함수형/SQL 혼합
성능 느림 (직접 처리) 최적화된 Catalyst 사용 Catalyst 사용
유연성 가장 유연함 중간 타입 지정 시 제약 있음

7. 결론

RDD는 Spark의 기본 데이터 추상화로서 분산 데이터 처리의 강력한 기반을 제공합니다. 하지만 Spark 2.x 이후로는 DataFrameDataset이 성능과 사용 편의성 측면에서 더 많이 사용됩니다. RDD는 여전히 복잡한 사용자 정의 연산이나 낮은 수준의 데이터 처리가 필요할 때 유용합니다.


8. 참고 자료

반응형