아파치 스파크의 주요 주제 -

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

아파치 스파크의 주요 주제

이 섹션에서는 Apache Spark의 기본 개념과 Apache Spark 성능 AWS Glue 튜닝에 대한 주요 주제를 설명합니다. 실제 튜닝 전략을 논의하기 전에 이러한 개념과 주제를 이해하는 것이 중요합니다.

아키텍처

Spark 드라이버는 주로 Spark 애플리케이션을 개별 작업자가 수행할 수 있는 작업으로 분할하는 역할을 합니다. Spark 드라이버의 책임은 다음과 같습니다.

  • main()코드에서 실행

  • 실행 계획 생성

  • 클러스터의 리소스를 관리하는 클러스터 관리자와 함께 Spark 실행자를 프로비저닝합니다.

  • Spark 실행자를 위한 작업 예약 및 작업 요청

  • 작업 진행 및 복구 관리

SparkContext객체를 사용하여 작업 실행을 위해 Spark 드라이버와 상호 작용합니다.

Spark 실행기는 Spark 드라이버에서 전달된 데이터를 보관하고 작업을 실행하는 작업자입니다. Spark 실행기의 수는 클러스터 크기에 따라 증가하거나 감소합니다.

Spark 드라이버, 클러스터 관리자, 작업자 노드의 JVM 실행자와의 작업자 노드 연결
참고

Spark 실행기에는 여러 개의 슬롯이 있으므로 여러 작업을 병렬로 처리할 수 있습니다. Spark는 기본적으로 각 가상 CPU (vCPU) 코어에 대해 하나의 작업을 지원합니다. 예를 들어 실행기에 CPU 코어가 4개인 경우 4개의 작업을 동시에 실행할 수 있습니다.

복원력이 뛰어난 분산 데이터세트

Spark는 Spark 실행기 전반에서 대규모 데이터 세트를 저장하고 추적하는 복잡한 작업을 수행합니다. Spark 작업용 코드를 작성할 때는 스토리지의 세부 사항을 고려할 필요가 없습니다. Spark는 병렬로 작동할 수 있고 클러스터의 Spark 실행기 간에 분할될 수 있는 요소 모음인 복원력 있는 분산 데이터세트 (RDD) 추상화를 제공합니다.

다음 그림은 Python 스크립트가 일반적인 환경에서 실행될 때와 Spark 프레임워크 (PySpark) 에서 실행될 때 메모리에 데이터를 저장하는 방법의 차이를 보여줍니다.

Python val [1,2,3 N], 아파치 스파크 레드 = sc.parallel lize [1,2,3 N].
  • Python — Python 스크립트를 val = [1,2,3...N] 작성하면 코드가 실행되는 단일 시스템의 메모리에 데이터가 보관됩니다.

  • PySpark— Spark는 여러 Spark 실행기의 메모리에 분산된 데이터를 로드하고 처리하는 RDD 데이터 구조를 제공합니다. 와 같은 코드를 사용하여 RDD를 생성할 수 있으며rdd = sc.parallelize[1,2,3...N], Spark는 여러 Spark 실행기에 데이터를 자동으로 분산하여 메모리에 보관할 수 있습니다.

    대부분의 AWS Glue 작업에서는 RDD를 통해 Spark를 사용합니다. AWS Glue DynamicFramesDataFrames 이는 RDD의 데이터 스키마를 정의하고 해당 추가 정보를 사용하여 상위 수준의 작업을 수행할 수 있는 추상화입니다. 내부적으로 RDD를 사용하기 때문에 다음 코드에서는 데이터가 투명하게 분산되고 여러 노드에 로드됩니다.

    • DynamicFrame

      dyf= glueContext.create_dynamic_frame.from_options( 's3', {"paths": [ "s3://<YourBucket>/<Prefix>/"]}, format="parquet", transformation_ctx="dyf" )
    • DataFrame

      df = spark.read.format("parquet") .load("s3://<YourBucket>/<Prefix>")

RDD에는 다음과 같은 기능이 있습니다.

  • RDD는 파티션이라는 여러 부분으로 나누어진 데이터로 구성됩니다. 각 Spark 실행기는 하나 이상의 파티션을 메모리에 저장하고 데이터는 여러 실행기에 분산됩니다.

  • RDD는 변경할 수 없습니다. 즉, 생성된 후에는 변경할 수 없습니다. DataFramea를 변경하려면 다음 섹션에 정의된 변형을 사용할 수 있습니다.

  • RDD는 사용 가능한 노드 전체에 데이터를 복제하므로 노드 장애 발생 시 자동으로 복구할 수 있습니다.

지연 평가

RDD는 두 가지 유형의 연산을 지원합니다. 하나는 기존 데이터셋에서 새 데이터세트를 생성하는 변환이고, 다른 하나는 데이터셋에서 계산을 실행한 후 드라이버 프로그램에 값을 반환하는 액션입니다.

  • 변환 — RDD는 변경할 수 없으므로 변환을 통해서만 변경할 수 있습니다.

    예를 들어, map 는 각 데이터셋 요소를 함수를 통해 전달하고 결과를 나타내는 새 RDD를 반환하는 변환입니다. 참고로 이 map 메서드는 출력값을 반환하지 않습니다. Spark는 사용자가 결과와 상호 작용할 수 있도록 하는 대신 미래를 위한 추상 변환을 저장합니다. Spark는 사용자가 작업을 호출할 때까지 변환에 영향을 주지 않습니다.

  • 조치 — 변환을 사용하여 논리적 변환 계획을 수립할 수 있습니다. 계산을 시작하려면,, 또는 같은 write 작업을 실행합니다. count show collect

    Spark의 모든 변환은 결과를 즉시 계산하지 않는다는 점에서 느립니다. 대신 Spark는 Amazon Simple Storage Service (Amazon S3) 객체와 같은 일부 기본 데이터세트에 적용된 일련의 변환을 기억합니다. 변환은 작업 시 결과를 드라이버에 반환해야 하는 경우에만 계산됩니다. 이러한 설계 덕분에 Spark를 더 효율적으로 실행할 수 있습니다. 예를 들어, map 변환을 통해 생성된 데이터셋이 행 수를 크게 줄이는 변환에 의해서만 소비되는 상황을 생각해 보십시오. reduce 그러면 매핑된 더 큰 데이터셋을 전달하는 대신 두 번의 변환을 모두 거친 작은 데이터셋을 드라이버에 전달할 수 있습니다.

Spark 애플리케이션 용어

이 섹션에서는 Spark 애플리케이션 용어를 다룹니다. Spark 드라이버는 실행 계획을 생성하고 여러 추상화로 애플리케이션의 동작을 제어합니다. 다음 용어는 Spark UI를 사용한 개발, 디버깅 및 성능 튜닝에 중요합니다.

  • 애플리케이션 — Spark 세션을 기반으로 합니다 (Spark 컨텍스트). 다음과 같은 고유한 ID로 식별됩니다. <application_XXX>

  • 작업 — RDD에 대해 생성된 작업을 기반으로 합니다. 작업은 하나 이상의 단계로 구성됩니다.

  • 스테이지 RDD용으로 만든 셔플을 기반으로 합니다. 스테이지는 하나 이상의 작업으로 구성됩니다. 셔플은 데이터를 재분배하여 RDD 파티션 간에 서로 다르게 그룹화하는 Spark의 메커니즘입니다. 예를 들어 특정 변환에는 셔플이 필요합니다. join() 셔플은 셔플 최적화 조정 실습에서 더 자세히 설명합니다.

  • 태스크 — 태스크는 Spark에서 스케줄링하는 최소 처리 단위입니다. 작업은 각 RDD 파티션에 대해 생성되며 작업 수는 스테이지의 최대 동시 실행 수입니다.

작업, 단계, 셔플, 태스크가 포함된 실행 계획.
참고

작업은 병렬성을 최적화할 때 고려해야 할 가장 중요한 사항입니다. 작업 수는 RDD 수에 따라 조정됩니다.

Parallelism

Spark는 데이터 로드 및 변환 작업을 병렬화합니다.

Amazon S3에서 액세스 로그 파일 (이름이 accesslog1 ... accesslogN 지정됨) 의 분산 처리를 수행하는 예를 생각해 보십시오. 다음 다이어그램은 분산 처리 흐름을 보여줍니다.

""
  1. Spark 드라이버는 여러 Spark 실행기에 걸친 분산 처리를 위한 실행 계획을 생성합니다.

  2. Spark 드라이버는 실행 계획을 기반으로 각 실행기에 작업을 할당합니다. 기본적으로 Spark 드라이버는 각 S3 객체 () 에 대해 RDD 파티션 (각각 Spark 작업에 해당) 을 생성합니다. Part1 ... N 그러면 Spark 드라이버가 각 실행기에 작업을 할당합니다.

  3. 각 Spark 작업은 할당된 S3 객체를 다운로드하여 RDD 파티션의 메모리에 저장합니다. 이러한 방식으로 여러 Spark 실행기가 할당된 작업을 병렬로 다운로드하고 처리합니다.

초기 파티션 수 및 최적화에 대한 자세한 내용은 병렬화 작업 섹션을 참조하십시오.

카탈리스트 옵티마이저

Spark는 내부적으로 Catalyst 옵티마이저라는 엔진을 사용하여 실행 계획을 최적화합니다. Catalyst에는 다음 다이어그램에 설명된 대로 Spark SQL DataFrame, 데이터 세트와 같은 높은 수준의 Spark API를 실행할 때 사용할 수 있는 쿼리 최적화 프로그램이 있습니다.

논리적 플랜은 Catalyst 옵티마이저를 거칩니다. Catalyst 옵티마이저는 최적화된 플랜을 출력하여 RDD로 전송합니다.

Catalyst 최적화 프로그램은 RDD API와 직접 작동하지 않으므로 일반적으로 상위 수준 API가 하위 수준 RDD API보다 빠릅니다. 복잡한 조인의 경우 Catalyst 최적화 프로그램은 작업 실행 계획을 최적화하여 성능을 크게 향상시킬 수 있습니다. Spark UI의 SQL 탭에서 Spark 작업의 최적화된 계획을 확인할 수 있습니다.

적응형 쿼리 실행

Catalyst 최적화 프로그램은 적응형 쿼리 실행이라는 프로세스를 통해 런타임 최적화를 수행합니다. Adaptive Query Execution은 런타임 통계를 사용하여 작업이 실행되는 동안 쿼리의 실행 계획을 다시 최적화합니다. Adaptive Query Execution은 다음 섹션에 설명된 대로 셔플 이후 파티션 병합, 정렬-병합 조인을 브로드캐스트 조인으로 변환, 스큐 조인 최적화 등 성능 문제를 해결하는 여러 솔루션을 제공합니다.

적응형 쿼리 실행은 AWS Glue 3.0 이상에서 사용할 수 있으며 4.0 (Spark 3.3.0) 이상에서는 AWS Glue 기본적으로 활성화됩니다. spark.conf.set("spark.sql.adaptive.enabled", "true")코드에서 를 사용하여 적응형 쿼리 실행을 켜고 끌 수 있습니다.

셔플 이후 파티션 통합

이 기능은 출력 통계를 기반으로 각 셔플 이후 RDD 파티션 (병합) 을 줄입니다. map 쿼리를 실행할 때 셔플 파티션 번호를 간단하게 조정할 수 있습니다. 데이터세트에 맞게 셔플 파티션 번호를 설정할 필요가 없습니다. 초기 셔플 파티션 수가 충분히 많으면 Spark는 런타임 시 적절한 셔플 파티션 번호를 선택할 수 있습니다.

둘 다 true로 설정된 경우 셔플 이후 파티션 병합이 활성화됩니다. spark.sql.adaptive.enabled spark.sql.adaptive.coalescePartitions.enabled 자세한 내용은 Apache Spark 설명서를 참조하십시오.

정렬-병합 조인을 브로드캐스트 조인으로 변환

이 기능은 크기가 크게 다른 두 데이터셋을 조인하는 경우를 인식하여 해당 정보를 기반으로 더 효율적인 조인 알고리즘을 채택합니다. 자세한 내용은 Apache Spark 설명서를 참조하십시오. 조인 전략은 셔플 최적화 섹션에서 설명합니다.

스큐 조인 최적화

데이터 스큐는 Spark 작업의 가장 일반적인 병목 현상 중 하나입니다. 데이터가 특정 RDD 파티션 (즉, 특정 작업) 에 치우쳐 애플리케이션의 전체 처리 시간이 지연되는 상황을 설명합니다. 이로 인해 종종 조인 작업의 성능이 저하될 수 있습니다. 스큐 조인 최적화 기능은 치우친 작업을 대략 같은 크기의 작업으로 분할 (필요한 경우 복제) 하여 정렬-병합 조인의 편차를 동적으로 처리합니다.

spark.sql.adaptive.skewJoin.enabled 기능은 true로 설정된 경우 활성화됩니다. 자세한 내용은 Apache Spark 설명서를 참조하십시오. 데이터 스큐는 셔플 최적화 섹션에서 자세히 설명합니다.