Upload
soo-kyung-choi
View
1.160
Download
2
Embed Size (px)
Citation preview
세상에서����������� ������������������ 가장쉬운����������� ������������������ Zeppelin����������� ������������������ Notebook����������� ������������������ ����������� ������������������
만들기
최수경����������� ������������������ @����������� ������������������ ����������� ������������������ NBT����������� ������������������ Partners
• 간단한����������� ������������������ 가이드����������� ������������������ 지만����������� ������������������ 처음����������� ������������������ 사용하시는����������� ������������������ 분들이����������� ������������������ 쉽게����������� ������������������ 개념을����������� ������������������ 잡으셨으면����������� ������������������ 해서����������� ������������������ 만들어����������� ������������������ 보았습니다.����������� ������������������ ����������� ������������������
• 저는����������� ������������������ spark����������� ������������������ +����������� ������������������ zeppelin을����������� ������������������ AWS상에서����������� ������������������ 사용하고����������� ������������������ 있습니다.����������� ������������������ ����������� ������������������
여기서 잠깐
• Zeppelin����������� ������������������ 은����������� ������������������ ‘제플린’����������� ������������������ 이라고����������� ������������������ 읽습니다.����������� ������������������
• 현대의����������� ������������������ 경비행선의����������� ������������������ 개발을����������� ������������������ 주장한����������� ������������������ 독일인의����������� ������������������ 이름으로,����������� ������������������ 독일어����������� ������������������ 발음����������� ������������������ ‘체펠린’����������� ������������������ 영어����������� ������������������ 발음����������� ������������������ ‘제플린’����������� ������������������ 입니다.����������� ������������������ 이����������� ������������������ 분의����������� ������������������ 이름을����������� ������������������ 따서����������� ������������������ 비행선����������� ������������������ 이라는����������� ������������������ 단어가����������� ������������������ 생겼다고����������� ������������������ 하네요.����������� ������������������ ����������� ������������������
Zeppelin Notebook이란?
• Hadoop에 HIVE가 있다면 Spark에는 Zeppelin이? ^^
• 사실 HIVE 보다 더 많은 기능을 제공합니다.
• Spark와 연동하는 쉬운 interface를 제공하는 오픈소스 도구
• interpreter방식의 명령과 수행을 제공 (iPython 노트북과 비슷하게 동작)
• html, sql, shell script, scala/python/java 등을 지원
왜 Zeppelin Notebook인가?
• Spark 과 함께 사용한다면, 확실히 빠릅니다.
• 데이터를 분석하고 싶은 사람의 입장에서, 한 화면에서 데이터의 추출, 처리, 분석을 (손쉽게!) 처리할 수 있습니다.
• 오픈소스 입니다. ^^
Zeppelin Notebook을 만드는 작업은 크게 세 단계
1. 데이터를 읽어온다.
2. 데이터를 처리한다.
3. 처리 결과를 저장/제공 한다.
1.����������� ������������������ 냉장고����������� ������������������ 문을����������� ������������������ 연다����������� ������������������
2.����������� ������������������ 코끼리를����������� ������������������ 넣는다����������� ������������������
3.����������� ������������������ 냉장고����������� ������������������ 문을����������� ������������������ 닫는다����������� ������������������
참.����������� ������������������ 쉽죠~잉?����������� ������������������ ^^;
하나. 데이터를 읽어온다!
• 로그파일이 있는 곳을 연결해서 읽어올 수 있습니다.
• 로그 파일도 기본 텍스트 타입이 있구요, 뭔가 사전처리를 해둔 (예를들면 parquet(파케이)같은) 타입이 있을 수 있습니다.
파케이����������� ������������������ 란?����������� ������������������ 기본����������� ������������������ 텍스트����������� ������������������ 형태의����������� ������������������ 로그����������� ������������������ 파일을����������� ������������������ 컬럼����������� ������������������ 스토어와����������� ������������������ 유사하게����������� ������������������ 처리하도록한����������� ������������������ 저장����������� ������������������ 방식으로,����������� ������������������ 속도����������� ������������������ 및����������� ������������������ 압축에서����������� ������������������ 우수한����������� ������������������ 성능을����������� ������������������ 보입니다.����������� ������������������
• S3에 로그가 있는 경우 val logs = sc.textFile(“s3n://daily_log_path/*”) logs.toDF.registerTempTable(“DAY_LOGS”)
• 이때 경로에 변수를 넣을 수 있습니다. val log_path = f”s3n://daily_log_path/$year/$month%02d/$day%02d/*/*” val logs = sc.textFile(log_path)
• 파케이 파일의 경우는 파티션 조건을 주고 읽습니다. val todayPQ = sqlContext.parquetFile(“s3n://parquet_daily_log_path/day=20150419”) todayPQ.registerTempTable(“DAY_PARQUET”)
•헉,����������� ������������������ 로그에����������� ������������������ 없는����������� ������������������ 컬럼이����������� ������������������ 필요한데요?����������� ������������������
• 파일이 아니라 DB라면?
• DB도 물론 연결할 수 있구요. 실행시 데이터를 가져오거나, 배치 작업을 수행해서 미리 데이터를 가져다 놓을 수도 있습니다.
• 하지만...어려운 문제 입니다.
• 이것이 바로 호환마마����������� ������������������ 보다����������� ������������������ 무섭다는?����������� ������������������ DATA DUPLICATION!
• 장점����������� ������������������ :����������� ������������������ 일단...����������� ������������������ 당면한����������� ������������������ 문제를����������� ������������������ 처리하는데는����������� ������������������ 편리하다.����������� ������������������
• 단점����������� ������������������ :����������� ������������������ 어느순간부터����������� ������������������ 복제된����������� ������������������ 데이터가����������� ������������������ 원본과����������� ������������������ 일치하는지����������� ������������������ 자신이����������� ������������������ 없어질����������� ������������������ 수����������� ������������������ 있다.����������� ������������������ 복제����������� ������������������ 작업����������� ������������������ 자체를����������� ������������������ 관리하는����������� ������������������ 일이����������� ������������������ 추가로����������� ������������������ 발생한다.����������� ������������������ 연결되어����������� ������������������ 있다고����������� ������������������ DB를����������� ������������������ 마구!����������� ������������������ 사용할����������� ������������������ 경우����������� ������������������ 빅데이터����������� ������������������ 처리����������� ������������������ 작업에����������� ������������������ 부하를����������� ������������������ 줄����������� ������������������ 수����������� ������������������ 있다.
• DB 접속정보를 입력하고, 읽어올 정보를 SQL로 정의한 후에 load()를 수행하면 필요한 정보를 데이터베이스로 부터 가져올 수 있습니다. val dbAddr = “111.1111.111.11:3300” val dbUser = “user_name" val dbPw = "password" val dbName = “test_db”
val dbTable = “”"( SELECT id AS user_id, nickname, created_at as join_date FROM users ) user_info”""
val jdbcDF = sqlContext.load("jdbc", Map( "url" -> s”jdbc:mysql://${dbAddr}/${dbName}?user=${dbUser}&password=${dbPw}", "dbtable" -> s”${dbTable}”)).persist()
jdbcDF.registerTempTable("USER_TABLE")
둘. 데이터를 처리한다!
• 테이블 형태로 등록해서 SQL문을 이용 할 수 있습니다.
• 또는 스칼라 코딩으로 조작 할 수도 있지요.
• 둘을 섞어가며 (스칼라����������� ������������������ 코딩으로����������� ������������������ 처리����������� ������������������ 후����������� ������������������ 테이블로����������� ������������������ 등록한다든지,����������� ������������������ 테이블로����������� ������������������ 등록된����������� ������������������ 것을����������� ������������������ 읽어서����������� ������������������ 스칼라����������� ������������������ 코딩으로����������� ������������������ 조작한다든지,����������� ������������������ 이걸����������� ������������������ 여러번����������� ������������������ 섞는다든지...) 작업하는 것도 물론! 가능합니다.
• SQL이 손쉽고 따로 공부 할 것도 없지만, 스칼라가 조금 더 빠르고, 폼이 납니다. ^^;
• 테이블 형태로 등록해서 SQL문을 이용 할 수 있긴 하지만,
• 가끔 수행이 안되는 경우도 있어요. 복잡한 SQL함수를 사용하고자 하는 경우에...
• 그러나 더욱 강력한 user define fuction을 등록 할 수 있으니 염려마시구요.
• registerTempTable()로 등록했다면, SQL을 통해 조회가 가능합니다. 입력 값을 받을 수도 있구요. 이때, 내가 등록한 함수를 사용할 수 있습니다. def getClickCount(input:Int) : Int = { val click_type = input.toString var cnt = 0 if (click_type != "error") cnt = 1 return cnt } sqlContext.udf.register("getClickCount", getClickCount _)
%sql SELECT day, age, SUM(getClickCount(click_type) ) FROM remain_report WHERE age >= 10 AND age <= 30 GROUP BY day, age ORDER BY day, age
• 그렇다면 이번엔, 스칼라 코딩으로 처리 해보죠.
• “가가����������� ������������������ 가가?”를����������� ������������������ 이해하시면����������� ������������������ 좋습니다.����������� ������������������ ^^;����������� ������������������ ����������� ������������������ ����������� ������������������
• 스칼라에서 당연한 경우에는 파라미터를 _ (underscore)로 대체 할 수 있습니다. 아래 두 라인은 똑같은 의미 입니다. val fmap = rdd.flatMap(line => line.split(" ")).map(word => (word,1)).reduceByKey{(a: Int, b: Int) => a + b}
val fmap = rdd.flatMap(line => line.split(" ")).map(word => (word,1)).reduceByKey(_+_)
• 빅데이터 에서는 보통 (key,value) 를 처리합니다.
• 로그에서 필요한 데이터만 잘라내서 key 부분에 넣고, 적절한 함수를 호출해 주면 됩니다.
val invalidLineCounter = sc.accumulator(0) val pairs = c_logs.map(s => ( try { s.split("\t")(1).split(":")(0) + "_" + s.split("\t")(1).split(":")(5) } catch { case _:Exception => { invalidLineCounter += 1 None } } , 1 ) ) val counts = pairs.reduceByKey(_+_) (사용자ID_날
짜, 노출횟수)
셋. 처리 결과를 저장/제공 한다!
• 가장 간단한 방법 : 화면에 EXCEL DOWNLOAD !! 아싸…
• 하지만 화면에 뿌려진 만큼만 download되기 때문에, 결과 화면 아래 빨간줄 메시지가 나온 경우에는 사용할 수 없습니다.
• 그런 경우에는? 파일로 쓰자!
• 결과를 직접 파일로 저장하는 경우
• 위치는 별도 (S3) 서버 또는 Zeppelin이 구동중인 서버에도 저장 가능합니다.
• 단 RDD 타입이어야 해요. resultRDD.coalesce(1).saveAsTextFile(“s3n://result_upload_path/test_result”)
• 결과를 메일로 보낼 수도 있구요. java 를 지원하니까요.
import java.util.* import java.mail.*
… 메일 본문을 만들고... 보내고....
Zeppelin Notebook을 만드는 작업은 크게 세 단계
1. 데이터를 읽어온다.
2. 데이터를 처리한다.
3. 처리 결과를 저장/제공 한다.
그림으로����������� ������������������ 정리해����������� ������������������ 보자면����������� ������������������
Log Parquet Log
RDD DF Temp Table
sc.textFile()sc.parquetFile()
rdd.toDF() df.registerTempTable()
rdd.map()
result file
map.saveAsTextFile()
df.saveAsParquetFile()
Map
sqlContext.sql()df.map()SQL
지금까지����������� ������������������ zeppelin����������� ������������������ notebook����������� ������������������ 만들기����������� ������������������ ����������� ������������������ 3단계를����������� ������������������ 살펴����������� ������������������ 봤습니다.����������� ������������������
더����������� ������������������ 자세한����������� ������������������ 내용은����������� ������������������ 직접����������� ������������������ 사용해����������� ������������������ 보시면서!����������� ������������������ ^^����������� ������������������
http://zeppelin.incubator.apache.org/docs/index.html