> For the complete documentation index, see [llms.txt](https://riverallzero.gitbook.io/summary/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://riverallzero.gitbook.io/summary/data-mining/mapreduce-and-spark.md).

# MapReduce and Spark

데이터 용량이 매우 커서 메모리에 올라가지 못하는 경우 파일을 다운로드하면 컴퓨터가 먹통이 될 수 있음.\
따라서 네트워크로 연결된 여러 대의 PC를 사용하여 데이터를 분산 처리해야 함.

### Hadoop DFS(Distributed File System)

<figure><img src="/files/EDUPDzMqrGE3pnudrs6H" alt=""><figcaption></figcaption></figure>

* 데이터를 여러 파일 서버에 분산 저장함.
* 프로그램이 분산된 데이터를 로컬에서 접근하고 저장할 수 있게 함.
* Name Node(master)와 Data Node(chunk)로 구성됨:
  * Name Node: 파일이 어디에 저장되었는지에 대한 메타데이터를 관리, 이 노드가 손상되면 파일 위치 정보를 잃기 때문에 안정적이고 내구성이 강해야 함
  * Data Node: 각 서버에서 데이터를 저장하며, 일반적으로 6\~128MB 크기의 블록 단위로 데이터를 저장, 동일한 데이터를 2배 혹은 3배 복사해 여러 노드에 분포시키며 장애가 발생하더라도 복구 가능하도록 설계
* 클라이언트는 Master(Name Node)에게 Chunk Server(Data Node)의 위치를 요청하고, Master로부터 정보를 받은 후 직접 Chunk Server와 통신함

### MapReduce

<figure><img src="/files/XPfHThUA4GFBl2CxZVib" alt=""><figcaption></figcaption></figure>

데이터를 순차적으로 읽고 처리하는 분산 프로그래밍 모델

1. Map: 데이터를 입력받아 단일 요소로 분할 (key-value 쌍 생성)
   * 같은 Key에 대해 많은 Pair가 생성되면 공간 문제 발생 가능. 이를 줄이기 위해 Combiner를 사용
   * Combiner는 Reduce Function이 덧셈의 교환법칙 및 결합법칙을 만족해야만 사용할 수 있음
2. Group by Key: 데이터를 Key별로 그룹화하고, 정렬 및 셔플링(shuffle) 수행
3. Reduce: Aggregation, Summarization, Filtering, Transformation 등을 수행

#### Failure Handling

* Map Worker Failure: 작업 중이거나 완료되지 않은 작업을 초기화한 후, 남아 있는 다른 Worker가 작업을 재할당받아 처리함
* Reduce Worker Failure: 진행 중인 작업만 초기화되고, 다른 Worker가 이를 재시작함
* Master Failure: Master가 중단되면 전체 프로그램이 종료되고, 클라이언트에 오류를 알림

### Spark

MapReduce는 반복(iterative) 처리로 매번 데이터를 디스크에 저장했다가 다시 읽어야 하므로 속도가 느리며 디스크 I/O와 네트워크 비용이 많이 발생해 성능 저하(Overhead)가 발생함\
Spark는 데이터를 Disk 대신 RAM에 저장하고, 캐싱(Caching)을 통해 빠르게 데이터를 처리하기 위해 설계됨

#### RDD (Resilient Distributed Dataset)

Spark가 사용하는 읽기 전용 데이터의 기본 단위

* 특징:
  * RDD는 불변(Immutable)하며, 한 번 생성된 RDD는 변경되지 않음
  * 변환(Transformation) 결과는 지연(Lazy) 평가되어, Action 명령이 실행될 때 수행됨
* 작동 방식:
  1. Transformation: 기존 RDD를 변환해 새로운 RDD를 생성
     * 변환은 지연 수행되어 Action이 실행될 때만 계산됨
  2. Action: RDD 변환을 실행하고 결과를 반환
* RDD 사용 방법:
  1. Create:
     * 변수로 생성: `rdd = sc.parallelize([1, 2, 3])`
     * 파일에서 생성: `rdd = sc.textFile('data.txt')`
  2. Transformation:

     * `flatMap()`: 데이터를 1차원 배열로 변환 ->`rdd2 = rdd.flatMap(lambda x: x.split(' '))`
     * `map()`: Key-Value 쌍 생성 ->`rdd3 = rdd2.map(lambda x: (x, 1))`
     * `reduceByKey()`: Key별로 데이터 집계 ->`rdd4 = rdd3.reduceByKey(lambda a, b: a + b)`

     <figure><img src="/files/hTO6Y8N8uLlx7tU2kbf4" alt=""><figcaption><p>각 단계별 collect() action을 수행한 결과</p></figcaption></figure>
  3. Action:
     * `rdd.collect()`: RDD 결과를 배열로 반환
     * `rdd.take(x)`: 상위 x개의 데이터를 반환
     * `rdd.count()`: RDD 요소 개수를 반환
     * `rdd.first()`: 첫 번째 요소 반환

### Hadoop MapReduce vs Spark

|        |   Hadoop  |     Spark    |
| :----: | :-------: | :----------: |
| 데이터 처리 |  Disk 기반  | In-Memory 기반 |
|   구현   | 상대적으로 어려움 |   상대적으로 쉬움   |
|   성능   |  상대적으로 낮음 |   상대적으로 높음   |
| 메모리 사용 |     낮음    |      높음      |
