Spark는 어플리케이션 당 하나의 인스턴스를 가지는 라이브러리처럼 동작한다. Spark로 작성하여 실행한 어플리케이션은 Driver와 Executer로 구분되어 실행된다. 이 두 프로세스는 JVM 프로세스 위에서 실행된다.
•
Driver
사용자가 작성 한 메인 코드 자체가 실행된다. 사용자의 Spark 프로그램 시작점인 SparkContext를 생성하며, Mesos, YARN과 같은 클러스터 매니져와 소통하여 실제 분산 연산 작업을 수행하는 Executer의 생성을 요청한다.
•
Executer
코드 내 주요 데이터 처리 코드가 Task의 형태로 실행된다. Task는 로컬환경 또는 클러스터 환경에서 Thread 단위로 병렬수행 된다.
Spark 프로그램을 비분산 로컬환경에서 실행하면 Executer는 별도로 실행되지 않고 Driver의 프로세스 내에서 Local Thread로 실행된다.
Spark 프로그램을 분산환경에서 실행하면 Executer는 배정받은 각 클러스터의 노드에서 프로세스로 실행된다.
SparkContext
Spark 프로그램을 실행할 떄 가장 먼저 생성해야 할 인스턴스이다. Spark Interactive Shell은 초기 생성 시 내부에서 자동적으로 SparkContext를 생성해주지만, 직접 생성하든 자동으로 생성해주든 작업을 수행하기 위해 무조건 생성해야 한다.
SparkContext가 수행하는 일은 다음과 같다.
•
데이터 연산, 저장, 캐싱을 수행하는 Executer 생성 요청
•
데이터를 담는 RDD 최초 생성
•
RDD 작업을 DAG 형태로 스케쥴링
RDD
RDD API
Spark에서 데이터를 담는 RDD는 Partition 단위로 분리되어 Executer에 존재하게 된다. RDD가 제공하는 다양한 API를 통해 데이터의 변경 연산, 또는 캐싱 작업을 수행할 수 있다. 데이터의 변경을 제공하는 API를 Transformation API, 데이터의 연산을 제공하는 API를 Action API라 부른다.
Transformation API
Transformation API를 통한 작업은 기존 RDD에 담긴 데이터를 직접 변경하는것이 아닌, 변경이 이루어진 새로운 RDD를 생성하도록 수행된다. Lazy Evaluation 특성을 가지는 Transformation API는 실제 데이터를 통해 연산하는것이 아닌, RDD 데이터의 변경 계획인 Query plan만을 생성한다. 한번 RDD에 담긴 데이터는 변경할 수 없는 Immutable한 데이터 구조를 가진다.
map, filter, distinct와 같은 API가 속한다.
Action API
Action API를 통해 RDD에 담겨진 데이터를 Driver로 가져오거나 외부 저장소에 저장할 수 있다. Action API는 실행될 때 마다 외부에서 데이터를 읽어와 최초 RDD의 생성부터 계획한 Transformation을 순차적으로 처리한다.
count, reduce, collect, take, saveAsTextFile와 같은 API가 속한다.
Persistence API
반복적으로 사용되는 RDD의 빠른 IO를 위해 Executer가 동작하는 노드의 메모리에 저장하는 Caching 기능도 지원한다. Caching된 RDD에 대해 Action 작업을 수행하면 외부에서 데이터를 읽어와 최초 RDD를 생성하는게 아닌, Caching된 RDD에서부터 작업을 처리하게 된다.
Caching은 RDD의 파티션 단위로 수행된다. 만약 하나의 Partition을 Caching 하기에 Executer의 메모리가 부족할 경우, 해당 Partition은 Caching되지 않는다. Caching되지 않은 해당 파티션은 디스크에 저장된 원본 파일로부터 다시 연산을 수행하게 된다.
persist, cache와 같은 API가 속한다.
RDD Fault-Tolerant
Spark은 특정 RDD가 만들어지기까지 수행 된 일련의 Transformation 작업들을 기록하는데, 이를 Lineage라 부른다. Lineage는 연산의 실패가 일어났을 때 손실된 데이터를 재연산하기위해 사용된다.
Fault-Recovery를 예로 들 수 있는 상황은 프로세스의 실패로 인해 Executer가 종료되어 Caching된 데이터가 손실된 상황이다. 이 경우, Spark는 자원 관리 매니저에 Executer 프로세스를 재요청한 후, 다음 Action API 호출 시에 손실된 캐시 데이터를 Caching하게 된다.