Spark 3.x로 올라오면서 Structured Streaming(이하 s.stream)이 지원되면서 group by, window 등 강력하면서도 다양한 기능을 streaming 에서도 사용할 수 있게 되었다.

기존 Discretized Streaming(이하 d.stream)과 다른 점 중 두드러지는 변화는 바로 checkpoint를 저장한다는 것이다.

checkpoint란?

streaming의 metadata 또는 kafka offset 등을 저장하는 데이터로 streaming app의 진행상황을 기록해둘 수 있다.

streaming app의 진행상황을 기록해두면, app이 종료되더라도 해당 지점부터 재수행이 가능하기 때문이다.

동작 원리나 여러가지 부가적인 기능 및 내용들이 많이 있지만, 자세한 것은 공식문서를 참고하길 바란다.

(안타깝게도 언제나 그렇듯 공식문서의 설명은 충분하지 않긴 하다)

공식문서: https://spark.apache.org/docs/latest/streaming-programming-guide.html#checkpointing

checkpoint 지정 방법

간단하다. SparkContext 또는 DataStreamWriter의 option을 주면 된다.

// 1. SparkContext에 지정하는 방법
val sparkConf = new SparkConf().setAppName("Checkpoint Example")
val checkpointDirectory: String = "/my/directory/checkpoint"

val ssc = new StreamingContext(sparkConf, Seconds(1))  
ssc.checkpoint(checkpointDirectory)
...


// 2. DataStreamWriter의 option으로 주는 방법
val dataset: Dataset[Schema] = getDatasetExample()
val checkpointDirectory: String = "/my/directory/checkpoint"

dataset.writeStream
    .option("checkpointLocation", checkpointDirectory)
    .trigger(ProcessingTime("10 seconds")
    .foreachBatch(saveFunction _)
    .queryName("Checkpoint Example")
    .start()

그렇다면 checkpoint는 어디다가 저장하는 것이 좋을까?

만약 물리장비에서 spark application을 운영한다면(아마도 spark on yarn), local directory에 저장하면 된다.
제일 간편하고, 성능이슈도 없다.

문제는 k8s환경에서(spark on k8s) 운영할 때인데, k8s환경의 local에 checkpoint를 저장하게 되면 pod이 내려갔을 때 checkpoint 정보를 모두 잃고 pod이 내려갔다가 올라오는 동안의 데이터가 유실되게 된다.

1. hdfs

hdfs는 좋은 선택지다.

그러나 secure hdfs를 사용하는 경우 i/o 성능이 뒷받침되지 않으면서 walCommit 시간이 늘어나서, micro batch 간격이 5~10초인 경우 lag이 점점 증가하는 경우가 발생할 수 있다.
(walCommit관련 내용은 추후에 또 다뤄보겠다)

secure hdfs를 사용하지 않는 경우 보안 이슈가 발생할 수 있으니 추천하기는 어렵다.

2. fuse

fuse는 사용하기는 편하겠지만 여전히 성능상의 이슈를 가지고 있다.
여러 pod에서 mount하기 때문에 write할 때 일종의 mutex를 획득해야 하는 경우가 많은데, 이 때 i/o 성능이 눈에 띄게 하락하게 된다.

역시나 walCommit 시간이 증가하는 이슈가 발생한다.

3. rbd

rbd는 거의 정답에 가까운 선택지다.
i/o 성능이 준수하고 옵션을 통해 persistence까지 보장이 가능하다. 필자도 현재 rbd를 checkpoint를 저장하는 용도로 사용하고 있으며, 아직 이슈가 된 적이 없다.

k8s환경에서 s.stream app을 운영하게 된다면, 성능 및 보안 측면에서 흠잡을 데 없는 rbd를 checkpoint directory로 사용하는 것을 강력하게 추천한다.

repartition vs coalesce

repartition()은 파티션의 개수를 늘리거나 줄일 수 있지만 coalesce()는 줄이는 것 만 가능하다.

성능 차이

파티션의 개수를 줄이는 경우에는 coalesce()를 사용하는 것이 더 좋은데, 그 이유는 바로 셔플때문이다.

coalesce()는 셔플을 수행하지 않기 때문에 성능 측면에서 repartition()보다 더 좋다.

구현

coalesce()함수가 구현되어있고, repartition()에서 coalesce()를 호출하는 형태로 구성되어있다.

코드 링크


여기까지는 많이 알려진 내용인데, 개발하다보니 순서를 보장한 상태에서 하나의 파일로 파티션을 묶어야 할 때가 있었다.
repartition()을 사용해서 묶었더니 정렬이 깨지거나 안되는 상황이 발생해서, 관련 테스트 결과를 기록한다.

  1. orderBy().repartition(1).write
    • 이 경우에는 partition 내부의 block 단위로 정렬이 된다.
    • 전체 파일이 정렬되지 않고 일부 정렬된 block들이 모여있는 상태처럼 보인다. (셔플이 수행되지 않은 것일까?)
    • 가끔 정렬이 되어있는 경우도 있었다. 왜인지 아시는 분은 댓글로 알려주시면 정말 감사드립니다..
  2. repartition(1).orderBy().write
    • 이게 어이없는 부분이었는데, 기존 100개의 partition을 읽고 해당 함수를 수행하니 100개의 partition으로 write했다.
    • 각각의 partition은 잘 정렬되어있었다.
    • 아마 1.에서의 block 단위가 100개의 partition으로 나뉘어진것이 아닌가 유추해본다.
  3. orderBy().coalesce(1).write
    • 제일 추천하는 방법이다.
    • 의도한대로 전체적으로 정렬이 되어있고, 1개의 partition으로 잘 묶여있다.
    • repartition(1)으로 묶었을 때와 비교해서 잘 정렬이 된 것으로 보아 repartition(1)으로 묶을때는 셔플이 수행된 것 처럼 보인다.
  4. coalesce(1).orderBy().write
    • 잘 동작한다. 직관적으로 1개로 묶고 정렬하는 방법이니 의도대로 잘 동작한다.
    • 역시나 2. 항목과 비교해보면 repartition() 방식이 아직도 잘 이해가 되지 않는다. 관련해서는 더 공부해봐야겠다.

coalesce() 동작 방식이 그림으로 잘 표현된 이미지가 있어서 첨부한다.

pipenv 환경에서 mysqlclient를 설치하려다 만난 에러들을 해결한 내용을 정리한다.

pipenv install mysqlclient

ld: library not found for -lzstd
clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: command 'xcrun' failed with exit status 1
----------------------------------------
ERROR: Failed building wheel for mysqlclient
ERROR: Command errored out with exit status 1:
  • xcrun을 못찾아서 발생한 에러다.
  • xcrun이란 xcode에서 사용하는 스크립트 실행 명령어로, xcode를 사용하지 않더라도 mac OS를 사용하는 경우 종종 사용된다.
  • xcode-select --install를 수행하면 해결되지만, 다음과 같은 에러를 또 만날 수 있다.
    xcode-select: error: command line tools are already installed, use "Software Update" to install updates

xcode-select: error: command line tools are already installed, use "Software Update" to install updates 해결 방법

  • https://developer.apple.com/download/all/
  • 위 링크에서 자신의 mac OS보다 낮거나 같은 버전의 Command Line Tools를 설치해준다.
  • 필자의 경우 10.15 버전의 mac OS를 사용중이어서, 10.15로 검색했지만 아무것도 나오지 않았다.
  • 그래서 10.14로 검색하니 다음과 같이 호환되는 버전이 나와서 해당 버전으로 설치했다.
    image
  • xcode를 사용하지 않는 필자로썬 뒤에 for Xcode가 거슬리지만, 무시하고 설치하자.

설치 후

  • 설치하고 나면 기존에 사용중인 개발 환경에서 몇몇 변화가 있을 수 있다.
  • 필자의 경우
    • pipenv관련 설정이 날라가거나 초기화되었다.
    • 기본 python3 사용 버전이 3.7이었는데, 3.9로 업데이트되었다.
  • 다음과 같이 해결했다.
    • zsh를 사용하고 있었기 때문에, ~/.zshrc에 다음 설정을 추가했다.
      export PYENV_ROOT={python3 기본 경로} // $ whereis python3의 결과
      export PIPENV_PYTHON=$PYENV_ROOT/shims/python
    • Pipfile에서 python 3.7버전을 사용중이었지만, 3.9로 수정해주었다.
  • 이후 pipenv 환경 삭제 후 재생성해주었다.

원래 하려던 건 mysqlclient 설치였다.

  • 참 길게 돌고돌았다. 이제 다음 명령을 수행해보자.
    $ pipenv install mysqlclient
    ... ✔ Success! ...
  • mysqlclient 설치가 완료되었다.

yum 사용

  • AMI2 이미지에는 apt-get 명령어가 먹히지 않는다. sudo yum update -yyum 명령을 업데이트 후 사용하자.
$ sudo yum update -y
$ sudo yum install python3
Loaded plugins: priorities, update-motd, upgrade-helper
No package python3 available.
Error: Nothing to do

image

aws 자체 이미지를 사용하자

  • python3 오타 없이 잘 썼는데 없다니, 말도 안된다.
  • 말이 된다. 기준이 aws이기 때문에 패키지 이름이 다르다. 다음 명령으로 aws용으로 생성된 python3 패키지를 확인할 수 있다.
$ sudo yum list | grep python3
...
(대충 python3가 포함된 yum 패키지 리스트)
...

// 해당 패키지만 설치를 원한다면 해당 패키지를, 특정 버전을 설치하고 싶다면 버전까지만 입력해도 무방하다
$ sudo yum install python37 // python3.7 설치 예시
$ python3 --version
Python 3.7.x
  • 설치하면 python3를 정상적으로 사용할 수 있다.
  • 유감스럽게도 pip3는 pip-3.7 이런식으로 걸어준다. 직접 pip3로 소프트 링크를 걸어주자.
$ cd /usr/bin
$ sudo ln -sfn pip-3.7 pip3 // pip-3.x 버전은 본인이 설치한 버전을 쓰면 된다
$ pip3 list
pip (9.0.3)
setuptools (36.2.7)
You are using pip version 9.0.3, however version 21.1.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

aws에서 새로운 인스턴스를 만들고 git을 연동하다 보면 꼭 마주치는 에러다.

[ec2-user@doolda]$ git push origin master
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

간단히 git에 ssh key를 추가해줌으로써 손쉽게 해결할 수 있다.

ssh key 생성하기

$ ssh-keygen -t rsa -C "{your-github-email}"
/ / 이후 엔터 3번

정상적으로 생성되었다면 public key, fingerprint 등 이것저것 만들었다는 안내 문구가 출력될 것이다.

다음 명령을 통해 우리가 필요한 ssh key를 출력한다.

$ cat ~/.ssh/id_rsa.pub

출력된 정상적인 ssh key는 ssh-rsa로 시작해서 위에서 입력한 {your-github-email}로 끝날 것이다.

ssh-rsa 부터 이메일 끝까지 모두 복사해둔다.

github에 생성한 ssh key 등록하기

  1. 본인의 github 계정의 Settings로 들어간다.
    image
  2. `SSH and GPG keys 탭으로 이동
    image
  3. New SSH Key 클릭
    image
  4. Key에다 복사해둔 ssh key를 입력하고 Title은 맘에 드는 이름을 지어주자.
    image
    Add SSH Key를 누르고 비밀번호를 입력하라는 창이 뜨면 입력해준다.

끝났다. 이제 다시 (아마도)git push origin master 명령을 수행해보면 정상적으로 동작할 것이다.

nvm(node version manager) 설치

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash

nvm 활성화

$ source ~/.nvm/nvm.sh

node.js 최신버전 설치

$ nvm install node

설치 확인

// node.js 버전 확인
$ node -v

// npm 버전 확인
$ npm -v

1. 서류 전형

준비

타 서류와 다르게 간단한 인적사항과 개발에 얼마나 관심이 있는지, 네이버에 얼마나 관심이 있는지 등에 대한 항목들을 기입했다.

개발에 대한 열정을 담으려고 노력했고, 실제로 구현하거나 사용한 기술 중 인상깊었던 내용을 포함했다.

결과

메일로 코딩테스트 진행 일정을 안내받았다.

  • 서류 합격 안내가 아니라, 서류 + 코딩테스트를 한번에 평가하기 때문에 서류를 제출하면 무조건 코딩테스트 안내를 받는다.

2. 코딩테스트 전형

코딩테스트는 이틀에 나눠서 진행됐다. 보통 하루에 모든 지원자의 테스트를 진행하는 것이 일반적인데, 거의 처음이라고 느껴질 정도로 이례적인 진행방식이었다.

준비

깊은 알고리즘 보다는 간단한 기본 알고리즘에 충실히 대비했고, 하루에 한 문제씩 풀면서 감을 유지하려고 노력했다.

전형

언제 봤는지는 기억나지 않는데, 생각보다 무난한 수준의 문제들이 출제됐다.

후기

개인적으로 백준 200문제 이상, 리트코드 탑100 중 20문제만 풀어봤어도 무난히 풀 수 있는 난이도라고 생각한다.

  • 서류 + 코딩테스트를 함께 평가한다고 안내받았던 것 같기도 하고..기억이 가물가물 한데, 일단 문제를 다 풀었다고 생각했고 합격 통보를 받았다.
  • 마찬가지로 코딩테스트를 잘 봤음에도 서류를 함께 평가해선지 탈락하는 경우가 있는 것 같다. 서류는 안본다고 생각해서 아무렇게나 막 쓰지 말자.
  • 타 기업과는 다르게 채점 TC를 많이 제공해주지 않는다.

3. 1차 면접 전형

준비

cs 기초(os, 네트워크, 자료구조, 알고리즘, db)위주로 충실히 공부했다. 자료가 워낙 많아서, 따로 책이 필요 없는 것 같다. 웹상에서 충분히 많은 좋은 자료를 구할 수 있고, 그 자료들을 바탕으로 직접 하나하나 정리해서 따로 문서화 했다. 이렇게 문서화한 자료는 몇번이고 반복독을 통해 숙지하고 이해하려고 노력했다.

웹상에서 구할 수 있는 면접 기출문제를 모두 준비했다. 역시 내 나름대로의 답변으로 문서화했고, 몇번이고 반복독을 통해 완전히 이해하려고 노력했다.

개인적으로 기사의 기출문제는 참고하는 것을 추천하지 않는다. 더 좋은 자료가 여러 블로그나 깃허브 repository 등등에 널리고 널렸다.

기술 외에 개인 PR을 위한 프로젝트 설명, 자기소개 등을 준비했다. 서류에 기입한 프로젝트는 정말 완전히 숙지하거나, 듬성듬성 참여한 프로젝트인 경우 기입하지 말 것을 강력하게 추천한다.

전형

그린팩토리에서 총 약 3시간정도(대기시간 포함) 진행했다. 워낙 지원자가 많다 보니 해당 시간의 면접자들이 각 층으로 흩어졌고, 1시간씩 2번 면접과 인성검사를 진행했다.

전형 과정은 자세히 언급하기에는 무리가 있을 것 같아 간단한 후기만 작성하려 한다. 양해를 부탁드린다.

  • IT회사다 보니 아무래도 기술 위주의 면접으로 진행됐고, 흔히들 알고 있는 꼬리물기 질문이 이어진다. 아무리 준비해도 그 끝은 블로그가 아니라 공식 문서에 있다는 걸 깨달을 수 있는 시간이다.
  • 개인적으로 정리한 예상 문제를 실제로 질문 받았는데, 나름대로 숙지한다고 숙지하고 면접실에 들어갔는데도 꼬리물기 질문에 탈탈탈 털렸다(역시 면접때는 꼭 준비를 덜 한 문제만 골라 물어본다).
  • 서류에 작성한 프로젝트 관련 기술적인 질문도 너무 러프하게 받아서 좀 당황했었다.
  • 면접관 분들이나 면접 안내해주시는 분들 모두 정말 친절하셨다.
  • 물론 복장은 자유다. 하지만 역시 정장 빌런은 있다
  • 간단한 다과와 물이 제공된다. 물 빌런에게는 너무나 감사한 배려였다.
  • 개인적으로 얼마나 개발자 같은지, 어떤 개발을 해 왔는지에 대한 면접이라고 생각이 드는 면접이었다.

면접이 모두 끝나면 인성 검사가 진행된다. 역시 친절하게 안내해 주시며, 부담스러운 인성 검사가 아니라 어떤 사람인지 궁금해하는 듯한 질문들로 이루어져있었다. 인적성이 아니라 인성이다.

인성 검사 까지 모두 끝나면 정말 1차 면접 전형이 모두 끝났다. 끝나면 간단한 기념품과 소정의 면접비, 복지 안내 자료를 제공해준다.

후기

IT회사 다운 면접이었다. 기술 위주인 것도 좋았고, 압박이 아니라 서로 소통하는 면접인 느낌이 들어서 좋았고, 어떤 점이 부족했는지 알 수 있는 면접이어서 좋았다.

결과

면접 후 2~3주 뒤 채용 홈페이지에서 결과를 확인 할 수 있었다.

4. 2차 면접 전형

준비

1차 때 할 수 있는 만큼 준비하자는 마인드로 공부했었는데, 2차 때는 뭘 공부해야 하지? 라는 생각이 많이 들었다. 1차 때 대답 못했던 부분들과 꼬리물기 하다 보면 대답 못 할 것들을 대비해서 더 깊이있는 공부를 하려고 노력했다.

당시 정말 준비하기 어려워했던 기억이 있다. 실제로 뭘 준비해야 할 지 몰랐기 때문이다.

전형

그린팩토리에서 약 1시간정도 진행했다. 1차에 비해서 확연히 면접자 숫자가 줄었다. 역시 편안한 분위기로 면접을 안내해주신다. 주말이었던 것으로 기억나는데, 그래서인지 건물이 엄청 조용했다. 조용함이 주는 편안함이 좋았다.

1차는 어느정도 면접관님들의 템플릿이 있었다고 가정하면 2차는 정말 면바면이었다.

모든 면접이 면바면이라지만, 다른 후기들을 들어보면 2차 면접은 정말 다양하게 진행됐다. 1차보다 더 깊은 기술 면접인 사람도, 기술은 없고 인성적인 면접을 본 사람도, 둘 다 본 사람도 있다. 1차 결과가 반영된 것인지, 면접관님들의 취향이 따로 있는건지 나로서는 전혀 알 수가 없다. 확실하게 말 할 수 있는 점은 아무리 준비해도 완벽한 준비는 없다는 것이다. 따라서 면접 전 날 까지 끊임없이 이것저것 모두 열심히 준비하다 보면, 좋은 결과가 있을 것 같다.

후기

정말 딱딱하지 않은 분위기에서 즐거운 면접을 진행했다. 면접이 끝나고 방을 나선 후 문을 닫았을 때 기분이 아직도 생생하다.

면접이 끝난 뒤에는 굿즈가 제공되며 바로 귀가할 수 있다.

결과

약 10일 뒤 채용 홈페이지에서 결과를 확인 할 수 있었다.

마치며

면접이 면접자에게 회사의 이미지를 어필할 수 있는 자리라고 느끼게 해준 면접이었다. 개인적으로 1, 2차 모두 긍정적인 느낌을 받았고 준비한 만큼 면접장에서 보여줄 수 있어서 좋았다. 그만큼 면접관님들이 이끌어 주신 덕분이지 않을까 싶다.

이번 공채는 약 3년만의 공채로, 기존 인턴에서 전환하는 신입 채용 제도에서 추가된 채용 방식이다. 오랜만에 진행한다고 해서 시스템적으로 아쉬운 부분 같은 것이 전혀 없었다. 오히려 3년동안 준비해온 느낌을 많이 받았다. 어느 회사나 마찬가지로 면접에서의 분위기와 입사 후 실제 분위기는 다르겠지만, 그럼에도 이런 곳에서 일해보고 싶다는 생각이 많이 들었다.

올해도 공채가 진행되고 있다. 준비해온, 준비할 분들께 조금이나마 도움이 되는 글이 되었으면 좋겠다.

혹시나 질문이 있으시다면 최대한 도와드리겠습니다 :)

  • 문제가 되는 부분이 있다면 댓글로 알려주세요. 즉시 수정하겠습니다 :)

'일상 > 취업' 카테고리의 다른 글

[현대자동차] R&D 전략기술 신입 연구원 지원 후기  (31) 2020.01.27

0. 후기를 시작하며..

그렇다. 사실 이 글은 반년 뒤 작성되어야했다. 반년 일찍 글을 쓰게 된(

이 글의 초안을 작성할 때는 무려 5월이었다...

) 이유가 절대 업데이트할 글이 없어서가 아니라는 점을 믿어주셨으면 좋겠다람쥐🐿️

1. 2020 상반기 후기

1.1 입사 후 부단히 노력하기

대애ㅐㅐㅐ앰 노력은 했지만 늘어나는건 실력이 아니라 야근시간 뿐이었다.

너무 안타깝게도 입사 전 쓰던 기술이랑 스택이 하나도 겹치지 않는 부서라 처음부터(처음이 맞긴 함ㅎ) 공부하는 기분으로 하루하루를 보냈다.

팀에서 사용하는 기술 스택은 hdfs, spark, scala, shell, python, js 등 백엔드보다는 데이터 처리에 더 가까운 편이었는데, scala는 아직도 어려워서 잘 못쓴다. shell같은 경우는 너무나도 재밌는 언어라 추가로 후술할 예정.

2019년 후기를 쓸 때만 해도 열정으로 가득찬 제2의 유노윤호였는데(팬입니다) 주말만 되면 집중력이 두세시간을 못넘는 나를 발견했다..

1일 1커밋은 아직도 유지하려고 노력중이다. 다만 1일 1커밋을 목표로 하다 보니 쓸데없는 커밋을 만들고 있는 나를 만나서 커밋 자체에 집착하기 보다는 개인 공부를 하는 시간을 갖는 데 의의를 뒀다.

1.2 2019 후기 작성

대단하게도 아직 단 한개의 후기도 작성하지 못했다. 변명하자면 IT계열 회사는 보통 하반기 위주로 공채를 진행한다..!(카카오 대규모 인턴, NHN 게임부문 공채, 라인 온라인 공채 등이 있었던건 함정)

올해 같은 경우 코로나로 인한 특수한 상황이라고 자기위로를 한 뒤 이제부터라도 글쓰는 시간을 늘려보려고 한다..

1.3 [DEPRECATED] 블로그와 함께 성장하기

이 항목은 게으름으로 인해 삭제되었습니다. 반성과 함께 다음 후기에는 부활하기를 간절히 바랍니다 <(_ _)>

1.4 블로그 이전

이것도 

당연히

 지키지는 못했지만 할말이 좀 있다. 작년 후기를 썼을 때만 해도 jekyll + 깃허브로 블로그 이사를 준비했었는데, 입사하면서 notion을 쓰기 시작했는데 쓰면 쓸수록 맘에 드는 앱이다. 자연스레 마크다운과 더 많이 익숙해졌고, 필요한 문서 정리를 할 때 마크다운 또는 notion으로만 작업하고있다. 그러다보니 notion으로 관리하면 편할 것 같다는 생각이 들었고 아직도 notion으로 완전히 이사할까 고민중이다.

그러나 깃허브는 아직도 여전히 매우 매력적인 선택지다. 마크다운에 익숙해진만큼 마크다운으로 작성한 문서를 바로 블로그로 업로드할 수 있는 환경을 구축하면 생산성뿜뿜이 보장될 것 같다(게으름이 이길 수 도 있다).

현재 운영중인 티스토리에서도 마크다운으로 글 작성을 지원하고있지만, 지원하지 않는 기능도 있고 생각보다 꽤나 

구리다

. 이 글도 티스토리 마크다운 에디터로 작성하려고 했는데 에디터 박스 크기 조절도 불가능하고, 애초에 한 줄만 노출해주는 에디터에서 무슨 문서를 작성할 수 있을까..?

분노와 함께 notion으로 글을 작성하니 역시 매우 편-안하다. 나중 이사를 위해서도 블로그 글을 노션에 백업해두는 작업을 해둬야겠다.

1.5 건강 챙기기

영양제는 평소에 잘 챙겨먹고있고, 운동을 하고있다! 웨이트위주로 헬스장에서 하고싶었지만 코로나로 인해 집에서 맨몸운동 루틴을 돌리고 있었는데 생각보다 맨몸운동도 좋은 것 같아서 계속 하는중이다. 최근 술🍺자리가 잦아져서 조금 걱정이 되지만.. 곧 건강검진🏥을 받을 예정이라 다음 후기에는 더욱 자세히 서술할 수 있을 것 같다!

놀랍게도 초안 작성 이후 업로드하기 전에 건강검진을 받았다.

그러나 하반기 후기를 위해 저장-☆

2. 상반기를 보내며 느낀점

2.1 회사생활

2.1.1 팀

몇몇 회사를 다녔지만 다 정말 좋은 팀이어서 개인적으로 너무 감사하고 운이 좋았던 것 같다. 이번에도 다들 너무 좋은 분들이라 행복하다😃

2.1.2 동기

신입으로 입사할 때 공채를 통하지 않는 경우(상시모집, 추천채용 등)는 동기가 별로 없는 경우가 많은데, 어쩌다보니 공채로 입사를 하게 됐고, 많은 동기들이 생겨났다. 처음에는 그냥 동기 많을수록 좋지! 라는 막연한 생각 뿐이었는데, 힘들때나 즐거울때나 곁에 친한 동기들이 있다는건 회사원이 가질 수 있는 큰 행복 중 하나가 아닐까 싶은 생각이 많이 들었다. 그래서 만약 공채와 수시채용에 둘 다 합격한 상황이라면, 강력하게 공채를 추천하고 싶다. 회사에서 팀원과도 좋은 관계를 유지할 수 있지만, 동기가 많을 수록 시야도 넓어지고, 동기와 함께 있을 때는 회사라는 공간이 너무 좁게 느껴지고 갇혀있는 느낌이 들지 않게 해준다.

물론 잘 맞지 않아서 친하지 않은 경우도 있을 수 있지만, 운 좋게 주변에 좋은 동기들이 넘쳐나서 감사히 회사를 다니는 중이다!헤헤

2.1.3 좋은 회사?

기껏해야 3개의 회사를 경험해봐서 잘 모를수도 있다😅

좋은 회사를 판단하는 가치가 모두 다르겠지만, 개인적으로 좋은 회사라기 보다는 좋은 팀이 더 중요한 것 같다. 아무리 회사 차원에서 이런저런 복지를 지원해준다고 해도 팀 사람들과 잘 맞지 않으면 불행한 회사생활을 하게 되는 것 같다.

내가 느낀 좋은 팀은 서로를 배려하고 탓하지 않으며 함께 성장

상생

하려는 의지가 가득한 팀이다❗

배려하는 팀에서는 누구나 실수할 수 있음을 인지하고 동료의 실수에 대해서 우리모두 다음부터 같은 실수를 반복하지 말자는 식의 대처를 하지만, 그렇지 않은 팀에서는 다음부터 실수하지 않게 하기 위해서라는 명분으로 망신을 주거나 잔소리까지 하는 것 같다. 이는 팀 전체의 분위기와 성장가능성을 낮추는 참 나쁜 대처방법인 것 같다😥

같은 팀인데도 서로를 탓하는 팀이 있다. 남 탓을 하는 것은 좋지 않다고 생각하는데, 심지어 같은 팀원끼리 탓한다면 어느 누가 팀 내에서 책임감을 가지고 일을 추진할 수 있을까?

함께 성장하려는 의지가 가득한 팀은 건설적인 논의를 통해 합리적인 결론을 도출하고 책임감을 가지고 각자 맡은 일을 잘 처리해서 서로서로에게 시너지를 주며 팀을 성장시킨다. 팀의 성장은 곧 팀원의 성장으로 이어지고 이런 선순환 구조가 반복될수록 팀원간의 technical한 신뢰와 유대가 끈끈해지다 보면 긍정적인 미래만이 남아 있는 것이 자명한 것 같다😍

3. 마무리

열심히 논 건 아닌데, 나름 다른 블로그 포스팅도 하긴 했는데, 후기에 욕심을 내서 이런저런 내용을 다 담으려다 보니 정작 글을 완성하지도 못하고 4개월이란 시간이 지나고 말았다ㅜㅜ

시간이 지난 만큼 수정할 부분이 보이지만, 그렇게 되면 상반기 후기에 걸맞지 않은 내용이 되기 때문에 하반기 후기에서 더 다루려고 한다.

기술적인 내용 포스팅도 더욱 추가해야겠다는 반성과 다짐과 함께, 미숙한 글을 여기서 마친다.

 

 

여기까지 읽어주신 분들께는 크나큰 감사의 말씀을 전합니다. 좋은 하루 보내세요 :)

'일상' 카테고리의 다른 글

2019 & 2020  (0) 2019.12.31

AWS에서 RDS 인스턴스 생성 후 로컬 연결이 안되는 경우가 있습니다.

다음 두 가지 방법을 실행해보시기를 추천드립니다.

해결 방법

  1. 보안 그룹에서 현재 사용중인 IP 추가

  • 보안 그룹 - {해당 보안 그룹} - 인바운드 규칙 편집 탭에 들어가서 MYSQL/Aurora 유형의 규칙을 추가

  • 현재 IP 또는 지정 IP를 소스로 추가

  1. 퍼블릭 엑세스 가능성을 예 로 설정

  • DB 인스턴스 수정 - 네트워크 및 보안 - 퍼블릭 엑세스 가능성
  • 처음 DB 인스턴스를 생성할 때 "아니요" 로 선택되어있음 (...)
  • 해당 설정을 "예" 로 바꿔줘야만 로컬(DB인스턴스 입장에서는 외부)에서 접속이 가능

Spark-AI SUMMIT 2020 에서 발표한 Fine Tuning And Enhancing Performance Of Apache Spark Jobs 세션을 나름대로 정리해보았습니다. 잘못된 정보나 오류가 있다면 언제나 지적 부탁드립니다 :)

튜닝에 영향을 줄 수 있는 요소들

모든 요소는 무조건적으로 많을수록 좋아지지 않고 적을수록 좋아지지 않는다.

각 요소들은 다른 요소의 performance에 영향을 준다.

Stage를 skip하는 경우는 좋다. Tuning을 잘 한 결과물.

Core 개수

많을 경우

  • 병렬성을 증가시킬 수 있음
  • 스케쥴링 시간이 늘어남

메모리

많을 경우

  • GC 시간이 늘어남

파티션

너무 많을 경우

  • 스케쥴링 issue 발생

너무 적을 경우

  • 병렬성 감소

데이터 쏠림 현상 (skew)

  • 성능 저하 발생
  • 클러스터에서의 불균형 발생

확인 방법

  • spark UI에서는 모든 task를 보여주지 않음
  • 메모리를 과도하게 사용하는 경우 의심 가능
    • 첫 job을 시작할 때는 data ingestion을 수행하느라 메모리를 많이 사용하기 때문에 skew로 판단하지 말 것
  • executor에 heartbeat가 끊긴 경우
  • RDD의 파티션 크기를 확인

해결 방법

repartition은 별게없으면서도 가장 효과적인 방법

  • 파티션을 narrow하게 만들기 좋음
  • 파티션의 개수를 늘려야 할 때는 repartition
  • 파티션의 개수를 줄여야 할 때는 repartition대신 coalesce를 사용

ingestion

파티션을 읽을 때 JDBC를 통해 spark option 사용

  • partitionColumn
    • 쏠린 파티션이 아니어야 함 (primary key 처럼)
    • MOD를 활용해보는 것도 좋음
  • lower/upperBound
  • numPartitions
    • 파티션의 최대 개수 지정

Cache / Persist

  • transformation한 뒤 DF를 재사용
  • cache를 사용하지 않으면 DF가 매번 생성됨
  • 너무 많이 cache를 사용하게 되면
    • 메모리 performance 저하
    • GC가 커짐
    • 오히려 성능 감소 가능성이 있음

그 외의 trick들

seq.par.foreach 사용하기

  • seq.foreach 보다 나은 성능
  • 병렬성 증가
  • race condition 또는 비결정적 결과(non-deterministic results)가 도출될 수 있음
    • accumulator 또는 synchronization을 사용해서 방지

UDF의 사용은 가능한 자제하기

  • UDF의 동작 원리
    • 모든 row를 object로 비직렬화
    • lambda 적용
    • 다시 직렬화
  • 더 많은 garbage 생성

스케쥴링

Round Robin

  • 쓰레드를 통해 하나의 application에서 여러 job을 동시에 돌릴 수 있음
  • 리소스 utilization에 더 좋음
  • 디버그와 튜닝을 더 어렵게 만듦

spark.scheduler.modeFAIR 로 설정하면

  • job들을 priority에 따라 pool로 묶음
  • pool에 속하지 않은 thread로부터 생성된 job은 default pool로 들어감
  • pool, weight, minShare의 config는 fairscheduler.xml에 있음

직렬화

Java Serializer

  • 대부분의 타입에서의 default로 사용됨
  • 모든 class와 호환 가능
  • 매우 유연한 편
  • 느림

Kyro Serializer

  • RDD shuffling과 간단한 type의 default로 사용됨
  • 빠름
  • SparkConf 에서 org.apache.spark.serializer.KyroSerializer 설정으로 사용 가능
  • 사용하고 싶은 class를 등록해서 원하는 만큼 적용 가능

GC 튜닝

GC 튜닝이 필요할 때

  • 너무 많은 객체가 할당된 경우
  • task가 끝나기 전에 Full GC 발생하는 경우
  • 너무 많은 RDD 캐시가 있는 경우
  • GC가 너무 빈번히 일어나는 경우
  • GC에 너무 많은 시간이 소요되는 경우
  • heartbeat가 끊긴 경우

Parrallel GC (spark의 default GC)

  • Heap size가 Young / Old generation으로 나뉨

각 상황 별 추천 해결 방법

  • minor GC가 자주 발생하는 경우
    • Eden과 Survivor size를 늘려줌
  • major GC가 자주 발생하는 경우
    • 너무 많은 객체가 생성된 경우 young size를 늘려줌
    • old size를 늘려줌
    • spark.memory.fraction 을 줄여줌
  • task가 끝나기 전에 Full GC가 발생하는 경우
    • GC를 통해 young space를 clear하는 것을 추천
    • memory를 늘려줌

G1GC

Appilication scale이 크거나 Heap size가 8GB보다 큰 경우 추천

  • 다음 옵션으로 설정 가능
    • -XX:ParrallelGCThreads = n
    • -XX:ConcGCThreads = [n, 2n]
    • -XX:InitiatingHeapOccupancyPercent = 35

마치며..

  • 성능 튜닝은 계속 반복되는 것이 정상
  • 튜닝은 상황에 따라 매번 달라짐
  • Spark UI, 로그, 사용가능한 모니터링 툴 등을 반드시 활용할 것
  • 대충 아무 trick이나 쓰지 말고 성능 저하의 주요 원인에 집중할 것
  • 완벽한 튜닝을 하기란 거의 불가능하다

+ Recent posts