[apache spark] [Spark Programming]1. Apache Spark 개요 및 설치

1. Apache Spark

- 하둡 기반의 맵리듀스 작업이 가진 단점들을 보완하기 위해서 만들어 진 프레임워크

 

- 하둡과 달리 인메모리(In-Memory) 기법을 활용한 데이터 저장 방식을 제공함으로써 머신러닝 등 

  반복적인 데이터 처리가 필요한 분야에서 높은 성능을 보여준다.

 

- 작업을 실행하기 전에 최적의 처리 흐름을 찾는 과정을 포함하고 있었기 때문에 성능 향상과 

  더불어 여러 개의 맵리듀스 잡을 직접 순차적으로 실행하는 수고를 덜어줬다.

 

- 이외에 실시간 스트리밍 데이터를 다루기 위한 스파크 스트리밍과 하이브와 연동도 가능한 

  스키마 기반 데이터 분석모듈인 스파크 SQL, R과 연동가능한 sparkR 등 데이터 처리 분야에 

  특화된 라이브러리도 지원해준다.

 

1) RDD(Resilient Distributed Dataset)

- 스파크가 제공하는 일종의 분산 데이터에 대한 모델이자 핵심 데이터 모델임.

 

- 다수의 서버에 걸쳐 분산 방식으로 저장된 데이터 요소들의 집합을 의미

 

- 동시에 병렬로 명령처리가 가능하고 장애가 발생할 경우 스스로 복구될 수 있는 내성을 가지고 있다.

 

* 스파크에서는 하나의 작업을 수행할 때 파티션 단위로 나눠서 병렬로 처리한다.

  또한 작업이 진행되는 동안 재구성되거나 네트워크를 통해 다른 서버로 이동하는, 셔플링 현상이 

  발생할 수 있다.

 

- 다수의 서버에 나눠져서 처리되기 때문에 유실이 발생할 수 있지만 이를 위해 원래 상태로 복구할 수

  있도록 RDD의 생성과정을 기록해 뒀다가 다시 복구해주는 기능을 가지고 있다.

 

- 또한 문제가 발생 시 전체작업을 처음부터 다시 실행하는 대신 문제가 발생한 RDD를 생성했던 

  작업만 다시 수행해서 복구를 진행한다. 

 

- 리니지(Lineage)

  스파크에서 RDD 생성 작업을 기록해 두는 것

 

  

(1) 생성 방법

- List, Set 같은 기존 프로그램의 메모리에 생성된 데이터를 이용하는 것

  -> 즉시 테스트해 볼 수 있어 테스트 코드 작성 등에 유용하게 사용됨

 

ex. Collection 을 이용

[Java Code]

JavaRDD<String> rdd = sc.parallelize(Arrays.asList("a", "b", "c", "d", "e"));

 

[Scala Code]

val rdd = sc.parallelize(List("a", "b", "c", "d", "e"))

 

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

[Python Script]

rdd = sc.parallelize(["a", "b", "c", "d", "e"])

 

 

- 로컬 파일시스템이나 하둡의 HDFS 같은 외부 저장소에 저장된 데이터를 읽어서 생성하는 방법

  -> 다양한 유형의 데이터 소스로부터 데이터를 읽고 RDD를 생성할 수 있다.

 

ex. 파일로부터 생성

[Java Code]

JavaRDD<String> rdd = sc.textFile("<path_to_file>");

 

[Scala Code]

val rdd = sc.textFile("<path_to_file>")

 

[Python Script]

rdd = sc.textFile("<path_to_file>")

 

- 기존에 생성돼 있는 RDD로부터 또 다른 RDD를 생성하는 방법

  - createRDD 같은 함수가 제공되는 것은 아니지만 기존 RDD의 모든 요소에 1을 더하는 등의 

    연산을 적용하면 "한 번 만들어지면 수정불가하다" 는 성질을 이용해 새로운 RDD 가 생성되는 것

 

ex. 기존 RDD로부터 새로운 RDD 생성

[Java Code]

JavaRDD<String> rdd1 = rdd.map(new Function<String, String>() {

@Override

public String call(String v1) throws Exception {

return v1.toUpperCase();

 

}

});

 

* JAVA 8 의 경우 다음과 같이 한다.

JavaRDD<String> rdd1 = rdd.map(v -> v.toUpperCase());

 

[Scala Code]

val rdd1 = rdd.map(_.toUpperCase())

 

[Python Script]

rdd1 = rdd.map(lambda s : s.upper())
 
(2) 연산
- 크게 Transformation. Action 으로 분류된다.
  - Transformatoion 
    어떤 RDD에 변형을 가해 새로운 RDD를 생성하는 연산
    기존 RDD는 바뀌지 않은 상태에서 변형된 값을 가진 새로운 RDD 가 생성된다.
    => RDD에 대한 생성 계보만 만들면서 쌓아 두고 액션 연산이 호출되면 한꺼번에 수행됨
       때문에 본격적인 작업 실행 전에 데이터가 어떤 방법과 절차에 따라 변형되어야 하는지 
       알 수 있다는 장점을 가진다.
 
  - Action
    해당 연산의 결과로 RDD가 아닌 다른 값을 반환하거나 아예 반환하지 않는 연산을 의미함
 
* sum(), stddev() 등의 메소드는 RDD 의 모든 요소가 숫자형인 경우에 사용이 가능함
* groupByKey() 메소드의 경우 키와 값싸으로 구성된 RDD 에서만 사용가능
 
2) DAG(Directed Acyclic Graph)
- 그래프 이론에서 사용되는 용어로 여러 개의 꼭짓점 또는 노드와 그사이를 이어주는 방향성을 지닌
  선으로 구성되고 그래프를 구성하는 꼭짓점, 노드 에서 출발하더라도 다시 원래의 꼭짓점으로 
  돌아오지 않도록 구성된 그래프 모델을 의미한다.
 
- 스파크에서 각 단계마다 최적화된 작업을 수행하기 위해 사용해야되는 데이터 처리용 라이브러리가
  다를 수 있기 때문에 서로 다른 라이브러리를 잘 조합해서 사용할 수 있도록 일련의 작업 흐름을 
  나타내는 워크 플로우 
 
(1) DAG 스케쥴러
- DAG 생성을 담당하는 부분
- 동작 방식
  - 전체 작업을 스테이지라는 단위로 나누어 실행하고 각 스테이지를 다시 여러 개의 태스크로 
    나누어 실행
 
  - 드라이버의 메인 함수에서 스파크 애플리케이션과 스파크 클러스터의 연동을 담당하는 스파크 
    컨텍스트라는 객체를 생성하고 이를 이용해 잡을 실행하고 종료하는 역할을 수행한다.
 
  - 스파크컨텍스트를 통해 RDD의 연산 정보를 DAG스케줄러에게 전달하면 스케줄러는 해당 정보를 
    이용해 실행 계획을 수립한 후 클러스터매니저에게 전달한다.
 
  - 전체 데이터 처리 흐름을 분석해 네트워크를 통한 데이터 이동이 최소화되도록 스테이지를 
    구성한다.
 
 
- 스케줄러의 역할: 대상 데이터의 크기를 줄여 셔플로 인한 부하를 최소화하는 것
 
 
(2) 좁은 의존성 vs. 넓은 의존성
- 좁은 의존성
  기존 RDD와 신생 RDD의 관계가 작은 경우를 의미( ex. 1:1 대응인 경우)
 
- 넓은 의존성
  기존 RDD가 여러 신생 RDD와 관계를 맺는 경우를 의미 (ex. 1:N 대응인 경우)
 
3) 람다 아키텍쳐
- 네이션 마츠가 제안한 모델로 빅데이터 처리를 위한 시스템을 구성하는 방법 중 하나이다.
 
- 빅데이터의 활용 분야가 넓어지면서 기존과 같은 대량의 데이터 처리는 몰론, 실시간 로그 분석과 
  같은 실시간 처리도 매우 중요해지는 상황이기 때문에 이를 만족 시키기 위한 아키텍쳐로 채택됨
 
-크게 일괄처리 계층과 속도 계층으로 나뉨
 
- 과정
  - 새로운 데이터는 일괄 처리 계층과 속도 계층 모두에 전달된다.
  - 일괄처리 계층은 원본 데이터를 저장하고 일정 주기마다 한 번씩 일괄적으로 가공해서 배치 뷰를 
    생성한다.
  - 속도 계층은 들어오는 데이터를 즉시 또는 매우 짧은 주기로 처리해 실시간 뷰를 생성한다.
  - 서빙 계층은 실시간 뷰와 배치 뷰의 결과를 적절히 조합해 사용자에게 데이터를 전달한다.
    - 서빙 계층을 거치지않고 배치 뷰 또는 실시간 뷰를 직접 조회할 수도 있다.
 
-> 일괄 처리 작업을 통해 데이터를 처리하되 아직 배치 처리가 수행되지 않은 부분은 실시간 처리를 
   통해 보완한다는 개념이다.
-> 이 경우 속도 계층의 처리 결과는 다소 정확하지 않을 수 있지만 추후에 일괄 처리 작업을 통해 
    다시 보정하는 형태로 운영될 수 있다,
 
2. Spark 설치
1) JDK
- 우선 open-jdk를 먼저 제거한 후 http://java.oracle.com 에서 jdk를 다운로드 받는다.
- Java8 의 경우 람다식을 사용하므로 이 후에 다뤄질 예정이기 때문에 Java8 버전이상으로 
  설치한다.
- 설치 후 설치 위치(PATH)를 환경 변수에 적용시켜준다.
 
2) Maven 설치
- 자바 프로젝트 통합 관리 도구로서 자바 개발자에게는 익숙한 도구이다.
http://maven.apache.org  에서 다운로드 받을 수 있으며 3.x 버전 중 바이너리 파일로 다운로드 
  받는다.
- 설치 후 설치 위치(PATH)를 환경 변수에 적용시켜준다.

- install new software -> http://alchim31.free.fr/m2e-scala/update-site 에서 설치 진행

- Eclipse 에서 Maven 프로젝트 실행 시 pom.xml 에 추가해야 되는 내용
[pom.xml]
...

   <dependency>
              <groupId>org.scala-lang</groupId>
              <artifactId>scala-library</artifactId>
              <version>스칼라 라이브러리 버전</version>
      </dependency>
      
      <dependency>
              <groupId>org.apache.spark</groupId>
              <artifactId>spark-core_코어 버전</artifactId>
              <version>스파크 버전</version>
      </dependency>
      
      <dependency>
              <groupId>org.apache.spark</groupId>
              <artifactId>spark-sql_스파크SQL 버전</artifactId>
              <version>스파크 버전</version>
      </dependency>

...

...
ex. 
   <dependency>
       <groupId>org.scala-lang</groupId>
       <artifactId>scala-library</artifactId>
       <version>2.11.11</version>
   </dependency>
      
   <dependency>
       <groupId>org.apache.spark</groupId>
       <artifactId>spark-core_2.11</artifactId>
       <version>2.3.3</version>
</dependency>
      
    <dependency>
    <groupId>org.apache.spark</groupId>
       <artifactId>spark-sql_2.11</artifactId>
       <version>2.3.3</version>
    </dependency>
...
 
 
3) Spark 설치
http://spark.apache.org 에서 다운로드 받을 수 있으며 Hadoop-2.8.3 버전을 사용하고 있기 
  때문에 다음과 같이 받았다.
 
 
 
 
- 설치하게되면 앞선 프로그램들과 마찬가지로 시스템 환경 변수에 설치 경로(PATH)를 저장한다.
- 정상작동하는지 확인하기위해 간단한 테스트를 시행한다.
 

 
- 추가적으로 ./bin/spark-shell 을 실행시켜본다.
 


 
- 아래 결과에 대한 실행 결과는 다음과 같다.
[Scala code]
val file = sc.textFile("file://[스파크 설치 위치(절대경로로 입력할 것!)]/README.md")
val words = file.flatMap(_.split(" "))
val result = words. countByValue
result.get("For"). get
 
[실행 결과]
res1: Long = 3

- 마지막으로 웹 브라우저에서 [자신의 IP 주소]:4040 으로 환경이 제공되는지 확인한다.
 
4) 파이썬 설치
- 스파크에서는 파이썬 2.6 / 3.4 이상의 버전을 지원한다. 
https://www.anaconda.com/download/ 에서 다운로드 받을 수 있다.
- 설치 이후 환경변수에 설치 경로를 추가시킨다.
 
5) 스칼라 IDE 설치
- 스파크는 스칼라, 파이썬, R 을 지원한다. 그 중 스칼라는 eclipse를 기반으로 IDE 가 제공된다.
  스칼라와 스칼라IDE 모두 설치한다.
  가능하다.
 
6) 파이썬 플러그인 설치
- Help - Install New Software - Add - Name 에 "PyDev" 입력 - PyDev 플러그인 설치
- Preference - PyDev - Interpreters - Python Interpreter 에서 새로운 인터프리터를 설치
- 바로 아래의 Libraries 탭을 눌러 스파크 라이브러리를 추가한다.
  New Egg/Zip(s) - [python 설치 경로]/lib/py4j-0.10.4-src.zip 을 설치한다.
- 마지막으로 Environment 에서 SPARK_HOME과 PYSPARK_PYTHON 변수를 생성한다.
  SPARK_HOME 은 스파크 설치 위치, PYSPARK-PYTHON은 파이썬 설치 위치를 입력한다.
 
 
2. 스파크 실행해보기
- 아래의 코드를 이용하여 spark 를 실행해보자
[WordCount.jar]
package Java.Spark;
 
import java.util.Arrays;
import java.util.Iterator;
 
import org.apache.commons.lang3.ArrayUtils;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
 
import scala.Tuple2;
 
public class WordCount {
 
public static void main(String[] args) 
{
if (ArrayUtils.getLength(args) != 3)
{
System.out.println("Usage: WordCount <master> <input> <output>");
return;
}
 
// SparkContext 생성
JavaSparkContext sc = getSparkContext("WordCount", args[0]);
 
try
{
JavaRDD<String> inputRDD = getInputRDD(sc, args[1]);
//JavaPairRDD<String, Integer> resultRDD = process(inputRDD);
JavaPairRDD<String, Integer> resultRDD = processWithLambda(inputRDD);
handleResult(resultRDD, args[2]);
}
catch(Exception e) 
{
e.printStackTrace();
}
finally
{
sc.stop();
}
 
}
 
public static JavaSparkContext getSparkContext(String appName, String master)
{
SparkConf conf = new SparkConf().setAppName(appName).setMaster(master);
return new JavaSparkContext(conf);
}
 
public static JavaRDD<String> getInputRDD(JavaSparkContext sc, String input)
{
return sc.textFile(input);
}
 
// Java 7
public static JavaPairRDD<String, Integer> process(JavaRDD<String> inputRDD)
{
JavaRDD<String> words = inputRDD.
flatMap(new FlatMapFunction<String, String>(){
public Iterator<String> call(String s) throws Exception
{
return Arrays.asList(s.split(" ")).iterator();
}
});
 
JavaPairRDD<String, Integer> wcPair = words
.mapToPair(new PairFunction<String, String, Integer>() {
public Tuple2<String, Integer> call(String s) throws Exception
{
return new Tuple2(s, 1);
}
});
 
JavaPairRDD<String, Integer> result = wcPair
.reduceByKey(new Function2<Integer, Integer, Integer>() {
public Integer call(Integer v1, Integer v2) throws Exception {
return v1 + v2;
}
});
 
return result;
 
}
 
// Java 8
public static JavaPairRDD<String, Integer> processWithLambda(JavaRDD<String> inputRDD)
{
JavaRDD<String> words = inputRDD.flatMap((String s) -> Arrays.asList(s.split(" ")).iterator());
JavaPairRDD<String, Integer> wcPair = words.mapToPair((String w) -> new Tuple2(w, 1));
JavaPairRDD<String, Integer> result = wcPair.reduceByKey((Integer c1, Integer c2) -> c1 + c2);
 
return result;
}
 
public static void handleResult(JavaPairRDD<String, Integer> resultRDD, String output) 
{
resultRDD.saveAsTextFile(output);
}
}
 
- 위의 코드는 Java 7 과 Java 8 모두 가지고 있으며 실행시에는 Java 8 Lambda 식을 활용한 코드가 사용된다.
- pom.xml 은 파일을 다운 받는 것을 추천한다.
 
- 실행은 HDFS 가 설치 되었다는 전제하에 다음의 명령어를 실행하며 만약 HDFS 가 설치 안되었다면 아래의 
  형식에 맞춰 사용하기 바란다.
 
[형식]
<spark-home-dir>/bin/spark-submit \
--class <package주소>.WordCount \
<jar 파일 경로>/<jar파일명>.jar \
local[*] \
<spark-home-dir>/README.md \
<spark-home-dir>/testresult
 
[실행 예시 - HDFS 설치 시]
./bin/spark-submit \
--class Java.Spark.WordCount \
hdfs://master:9000/jar/spark/WordCount.jar \
local[*] \
hdfs://master:9000/input/README.md \
hdfs://master:9000/output/WordCountResult
 
 
 
[실행 화면 - 확인]
[hadoop@master spark-2.3.0-bin-hadoop2.7]$ hadoop fs -cat /output/WordCountResult/part*
(package,1)
(this,1)
(Because,1)
(Python,2)
(cluster.,1)
(its,1)
([run,1)
(general,3)
(have,1)
(pre-built,1)
(YARN,,1)
(locally,2)
(changed,1)
(locally.,1)
(sc.parallelize(1,1)
(only,1)
(several,1)
.....
 

파일 첨부 : pom.xml

 

[출처] https://m.blog.naver.com/slykid/221186930260

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED