728x90
반응형

Gitmoji

Gitmoji란 git + emoji를 합친 말로 gitmoji를 이용하여 commit message를 작성할 때 어떤 종류의 변경/커밋인지 아이콘으로 표시할 수 있는 기능이다.

gitmoji를 사용하면 가독성이 올라가기도 하며 커밋 자체가 예뻐진다!

이렇게 앞에 emoji가 붙는다.


IntelliJ / PyCharm 에서 설치법

보통 코드 commit 을 IntelliJ나 PyCharm 에서 하므로 여기에 적용해 두면 편하다.

1. shift 키 두번 눌러서 'plugins' 검색

2. Marketplace에 gitmoji 검색

3. 설치하고 재시작 해주면 끝이다!


아래는 gitmoji 아이콘별 코드, 설명이다.

아이콘 코드 설명 원문
🎨 :art: 코드의 구조/형태 개선 Improve structure / format of the code.
⚡️ :zap: 성능 개선 Improve performance.
🔥 :fire: 코드/파일 삭제 Remove code or files.
🐛 :bug: 버그 수정 Fix a bug.
🚑 :ambulance: 긴급 수정 Critical hotfix.
:sparkles: 새 기능 Introduce new features.
📝 :memo: 문서 추가/수정 Add or update documentation.
💄 :lipstick: UI/스타일 파일 추가/수정 Add or update the UI and style files.
🎉 :tada: 프로젝트 시작 Begin a project.
:white_check_mark: 테스트 추가/수정 Add or update tests.
🔒 :lock: 보안 이슈 수정 Fix security issues.
🔖 :bookmark: 릴리즈/버전 태그 Release / Version tags.
💚 :green_heart: CI 빌드 수정 Fix CI Build.
📌 :pushpin: 특정 버전 의존성 고정 Pin dependencies to specific versions.
👷 :construction_worker: CI 빌드 시스템 추가/수정 Add or update CI build system.
📈 :chart_with_upwards_trend: 분석, 추적 코드 추가/수정 Add or update analytics or track code.
♻️ :recycle: 코드 리팩토링 Refactor code.
:heavy_plus_sign: 의존성 추가 Add a dependency.
:heavy_minus_sign: 의존성 제거 Remove a dependency.
🔧 :wrench: 구성 파일 추가/삭제 Add or update configuration files.
🔨 :hammer: 개발 스크립트 추가/수정 Add or update development scripts.
🌐 :globe_with_meridians: 국제화/현지화 Internationalization and localization.
💩 :poop: 똥싼 코드 Write bad code that needs to be improved.
:rewind: 변경 내용 되돌리기 Revert changes.
🔀 :twisted_rightwards_arrows: 브랜치 합병 Merge branches.
📦 :package: 컴파일된 파일 추가/수정 Add or update compiled files or packages.
👽 :alien: 외부 API 변화로 인한 수정 Update code due to external API changes.
🚚 :truck: 리소스 이동, 이름 변경 Move or rename resources (e.g.: files paths routes).
📄 :page_facing_up: 라이센스 추가/수정 Add or update license.
💡 :bulb: 주석 추가/수정 Add or update comments in source code.
🍻 :beers: 술 취해서 쓴 코드 Write code drunkenly.
🗃 :card_file_box: 데이버베이스 관련 수정 Perform database related changes.
🔊 :loud_sound: 로그 추가/수정 Add or update logs.
🙈 :see_no_evil: .gitignore 추가/수정 Add or update a .gitignore file.

 

728x90
반응형
728x90
반응형

가상 면접 사례로 배우는 대규모 시스템 설계 기초

내가 보려고 정리하는 내용

그냥 읽기만 하면 기억에 잘 남지 않으니 간단하게 정리하면서 읽어보자.

 


제 1장. 사용자 수에 따른 규모 확장성

1.1 DNS, 로드밸런서, 데이터베이스 다중화

사용자가 웹사이트에 접속하여 무언가 요청을 하는 간단한 시스템에서 확장성을 다룬다.

되게 오랫동안 기억 저 안쪽에만 넣어둔 'DNS' 가 나왔다.

  • DNS: 도메인 이름(google.com)의 IP 주소를 알려준다.

사용자가 늘어감에 따라 하나의 서버에서 요청/처리를 하는 것이 아니라 여러 서버를 두어야 한다.

  • 데이터베이스
    • RDBMS
    • NoSQL
    • 각각의 장단을 고려해 바람직한 데이터베이스를 사용해야 한다.

예를 들어 아주 낮은 응답 지연시간이 요구되거나 다루는 데이터가 정형 데이터가 아닐 경우 NoSQL을 사용해야 하는 경우가 있을 수  있다.

성능을 개선하는 방법으로 확장에 대해 소개한다.

  • 수직적 규모 확장(scale up): 서버에 고사양 자원을 추가하는 행위
  • 수평적 규모 확장(scale out): 더 많은 서버를 추가하여 성능을 개선하는 행위

웹 서버에 너무 많은 부하(사용자가 많아짐)가 생기면 웹 서버가 다운될 수 있어 이를 막기 위해 로드밸런서를 도입해야한다.

로드밸런서는 웹 서버들에게 트래픽을 고르게 분산하는 역할을 한다.

우리가 흔히 LB 구성한다고 할 때의 그 LB이다.

이렇게 분산된다면 웹 계층의 경우 분산된 서버끼리 트래픽을 골고루 나누게 되는데 데이터베이스의 경우 어떻게 해결할까? 장애의 복구나 다중화가 필요하다.

데이터베이스 다중화

  • 쓰기 연산은 주 데이터베이스 서버로, 읽기 연산은 부 데이터베이스 서버 여러대로 분산시킬 수 있다.
  • 이를 통해 더 나은 성능을 기대할 수 있고
  • 데이터를 보존할 수 있어 안정성이 높아진다.
  • 하나의 데이터베이스 서버에 장애가 발생하더라도 다른 서버의 데이터를 가져와 계속 서비스 할 수 있어 가용성이 높아진다.

1.2 캐시

캐시는 값비싼 연산 결과나 자주 참조되는 데이터를 메모리에 두어 뒤이은 요청이 빨리 처리될 수 있도록 하는 저장소이다.

캐시 계층은 데이터가 잠시 보관되는 곳으로 데이터베이스보다 훨신 빠르다. 데이터 요청이 올 때 데이터베이스를 참조하기 전에 캐시에서 데이터를 반환할 수 있도록 한다.

캐시를 사용할 때 고려할 점

  • 캐시를 쓰는 바람직한 상황
  • 영구적으로 보관할 데이터라면 데이터베이스에 보관
  • 만료에 대한 정책
  • 일관성 유지
  • 캐시 단일 서버 장애 대응(캐시 분산)
  • 캐시 메모리 크기
  • 어떤 데이터를 캐시에서 삭제할지(LRU, LFU, FIFO 등 대학생 때 배웠던 그것!)

1.3 CDN(콘텐츠 전송 네트워크)

CDN은 이미지, 비디오, CCS, java script 파일 등을 캐시할 수 있는 정적 콘텐츠를 전송하는데 쓰이는, 지리적으로 분산된 서버의 네트워크이다.

CDN은 보통 제 3 사업자에 의해 운영되어 데이터 전송 양에 따라 요금을 내게 된다.

정적 콘텐츠를 웹 서버를 통해 서비스하는 것이 아니라 CDN을 통해 제공해 더 나은 성능을 보장할 수 있다.

1.4 무상태(stateless) 웹 계층

서버의 수평적 확장에서 고려해야 할 부분으로 공유되어야할 상태 정보를 웹 계층에서 제거해야한다.

공유 데이터는 NoSQL 등에 저장할 수 있다.

 

1.5 데이터 센터

엄청 커져서 분산된 데이터 센터가 만들어졌다면, 즉 다중 데이터센터 아키텍처가 만들어진 상황이라면

동기화, 테스트 ,배포 등에 고려할 점들이 많다.

시스템 컴포넌트들을 분리하여 독립적으로 확장할 수 있도록 구성해야한다.

 

1.6 메시지 큐

비동기 통신을 지원하기 위한 메시지 큐는 메시지의 버퍼 역할을 하며 비동기적으로 전송한다.

카프카, Rabbit MQ 등에서 다뤄볼 수 있다.

메시지 큐를 이용하면 서비스 또는 서버간 결합이 느슨해져서 규모 확장성을 보장하는 애플리케이션을 구성하기 좋다.

 

1.7 로그, 메트릭 그리고 자동화

로그: 애플리케이션에서 발생하는 개별 이벤트로 에러 로그를 통해 오류를 찾을 수 있다.

메트릭: 시스템의 상태를 파악할 수 있다.

  • CPU,  메모리 등 호스트 단위 메트릭
  • 캐시 성능, 디비 성능인 종합 메트릭
  • 재방문, 일별 능동 사용자 같은 것이 핵심 비즈니스 메트릭이라고 한다.

자동화: ci/cd등을 통한 생산성을 높이는 도구 또는 코드 검증 절차 자동화 등 개발 생산성을 향상 시키는 것

 

1.8 데이터베이스의 규모 확장

데이터베이스 또한 수직적/수평적 확장을 할 수 있다.

수직적 확장

  • 스케일업
  • 기존 서버에 더 많은 자원(CPU, RAM 등)을 증설하는 방법
  • 많은 양의 데이터를 보관하고 처리할 수 있다.
  • 단일 포인트 실패로 인한 문제점이 크다.
  • 비용이 많이 든다

수평적 확장

  • 데이터베이스의 수평적 확장은 샤딩이라고 부른다.
  • 더 많은 서버를 추가함으로써 성능을 향상시킨다.
  • 대규모 데이터베이스를 샤드라고 부르는 작은 단위로 분할하는 기술로 각각의 샤드에 보관되는 데이터 사이에는 중복이 없다.

 


안정적인 시스템 규모 확장을 위해서는

웹 계층은 무상태 계층으로, 모든 계층에는 다중화를 도입하고 데이터 계층 샤딩은 필수

각 계층은 독립적 서비스로 분할하며 모니터링과 자동화 필수

728x90
반응형
728x90
반응형

오류

error: scala.reflect.internal.MissingRequirementError: object java.lang.Object in compiler mirror not found.

 

원인

scala 2.11  버전과 java SDK 버전이 맞지 않아 발생하는 오류

 

해결방법

scala 버전에 맞게 java SDK를 8 버전으로 바꾼다.

나의 경우 9버전이었다.

728x90
반응형
728x90
반응형

쾅쾅 부딪히면서 배운 스파크 관련 내용을 그냥 실무에 적용만 해버리고 말면 다 까먹을 것 같아서 정리를 좀 해보려고 한다.

(근데 진짜 쾅쾅 부딪혔다는 점...ㅠ)


Spark 를 띄울 때 가장 기본적으로 설정해야 하는 요소인 Driver와 Executor 사이즈와 개수를 설정하는 방법과 관련 내용을 정리해 보자.

Spark job을 제출한 예시이다.

spark3-submit --master yarn --deploy-mode cluster --queue default --conf spark.dynamicAllocation.enabled=False --conf spark.sql.parquet.writeLegacyFormat=True --conf spark.sql.catalog.spark_catalog.type=hive --files hdfs://nameservice1/user/myConfig.conf --num-executors 3 --executor-cores 2 --executor-memory 4g --driver-memory 2G --name my_test_spark_job --class myApp.MyClass hdfs://nameservice1/user/my-jar.jar
  • executor 수를 정했고: --num-executor 3
  • executor 코어 수를 정했고: --executor-cores 2
  • executor 메모리 크기를 정했다: --executor-memory 4g
  • 추가로 driver 메모리 크기도 정했다: --driver-memory 2g

 

스파크 관련 기초 글은 아래를 참고하자!

2023.12.03 - [코딩해/Kafka, Spark, Data Engineering] - [Spark] 스파크 구조와 실행 과정 | 스파크 기초

 

[Spark] 스파크 구조와 실행 과정 | 스파크 기초

아주 기본적인 내용이지만 글로 정리해보려고 한다. 스파크 처음하는 사람들에게 조금이라도 도움이 될까 해서! 스파크는 Spark Application과 Cluster manager로 구성되어 있다. 그리고 Spark Application에

haonly.tistory.com


Executor에 관한 좀 더 깊은 내용을 알아보자

  • Executor는 캐싱과 실행을 위한 공간을 갖고 있는 JVM이다.
  • Executor와 driver 사이즈는 하나의 노드나 컨테이너에 할당된 자원보다 많은 메모리나 코어를 가질 수 없다.
  • Executor의 일부 공간은 스파크의 내부 메타 데이터와 사용자 자료구조를 위해 예약되어야 한다.(평균 약 25%) 이 공간은 spark.memory.fraction 설정으로 변경 가능하며, 기본값은 0.6으로 나머지 0.4는 캐싱에 쓰인다.
  • 하나의 partition이 여러 개의 executor에서 처리될 수 없다 --> 하나의 partition은 하나의 executor에서 처리

 

Executor 크기

Executor 크기는 어떻게 설정하면 좋을까?

executor의 수는 많게, 크기(core)를 작게 설정하면 

  1. OOM, spill 등이 생길 수 있다. -> 처리할 자원이 충분하지 않기 때문이다.
  2. 자원을 효율적으로 사용할 수 없다. -> 같은 노드 내 executor끼리 통신에도 비용이 필요하다.

executor의 수는 적게, 크기(core)를 크게 설정하면

  1. 너무 큰 executor는 힙 사이즈가 클수록 GC가 시작되는 시점을 지연시켜 Full GC로 인한 지연을 더욱 크게 만든다.
  2. executor당 많은 수의 코어를 쓰면 동시 스레드가 많아지면서 스레드를 다루는 HDFS의 제한으로 인해 성능이 더 떨어질 수도 있다. 

효율적인 세팅을 위해서

  • GPU 자원 기준으로 executor의 개수를 정하고,
  • executor당 메모리는 4GB 이상, executor당 core 수는 (1 < number of GPUs <= 5) 기준으로 설정한다면 일반적으로 적용될 수 있는 효율적인 세팅이라고 할 수 있다.

 

이상은 클러스터 환경에 따른 기본 설정을 고려해 볼 세팅 값이었고,

사용자가 제출한 애플리케이션의 규모, 성능 등을 고려하여 적절히 자원을 더 늘리거나 줄일 수 있어야 한다.

 

스파크 기본 shuffle partition은 200으로 설정되어 있다.(내 클러스터만 그럴 수도 있다...!)

나의 경우 위의 제출 기준(--num-executors 3 --executor-cores 2 --executor-memory 4g)로는 원하는 성능이 나오지 않았으며 memory spill이 많이 일어나 아래와 같이 변경 적용하였다.

--num-executors 3 --executor-cores 100 --executor-memory 18g

이때 partition은 300개로 유지될 수 있도록 해주었다.

 

 

다음 글로는 스파크 properties 정리(공식 문서), 파티션 개수, 크기 정하는 내용, 스파크 튜닝한 내용 등을 정리해 봐야겠다.

스파크 어려운데 너무 강력한 놈이라서 많이 배워야겠다.

728x90
반응형
728x90
반응형

아주 기본적인 내용이지만 글로 정리해보려고 한다.

스파크 처음하는 사람들에게 조금이라도 도움이 될까 해서!


스파크는 Spark Application과 Cluster manager로 구성되어 있다.

그리고 Spark Application에는 Driver와 Executor라는 두가지 JVM 프로세스가 포함되어 있다.

  • Driver: Driver는 SparkSession/SparkContext를 생성하고, Job 을 제출하고 task로 변환하고, worker 간의 task 실행을 조정하는 주요 프로세스이다.
  • Executor: Executor는 주로 특정 계산 작업을 수행하고 결과를 driver에게 반환하는 일을 담당한다.

Spark Application은 실제 일을 수행하며, Cluster manager는 Spark Application 사이에 자원을 중계해주는 역할을 담당한다.

Spark Application

<Spark The Definitive Guide> 참고

Spark Driver 와 Executor에 대해 더 자세히 살펴보자.

  • Spark Driver: 한 개의 노드에서 실행되며, 스파크 전체의 main() 함수를 실행한다. 어플리케이션 내 정보를 유지/관리한다. 사용자가 제출한 job을 task 단위로 변환하여 executor에게 전달한다.
  • Executor: 다수의 worker 노드에서 실행되는 프로세스로 spark driver가 할당한 작업(task)를 수행하여 결과를 반환한다. 또한 블록매니저를 통해 cache 하는 RDD를 저장ㅎ나다.

Cluster Manager(클러스터 매니저)

Cluster Manager 는 스파크와 붙이거나 뗄 수 있는 컴포넌트로, Spark Application의 리소스를 효율적으로 분배하는 역할을 담당한다.

Spark는 executor에 task를 할당하고 관리하기 위하여 Cluster manager에 의존한다.

Spark는 단지 cluster manager와 통신하며 할당 가능한 Executor를 전달받으며 clustor manager의 상세 동작을 알지는 못한다.

스파크3.0 기준으로 Cluster manager의 종류는

  • Spark StandAlone
  • Hadoop Yarn
  • apache mesos
  • kubernetes 등이 있다.

Spark Application 실행 과정(흐름)

Spark를 사용할 때의 대력적인 실행 흐름이다.

  1. 사용자가 spark-submit을 통해 애플리케이션을 제출한다.
  2. Spark driver가 main()을 싱행하여 SparkContext를 생성한다.
  3. SparkContext가 Cluster Manager와 연결된다.
  4. Spark Driver가 Cluster Manager로부터 Executor 실행을 위한 리소스를 요청한다.
  5. Spark Context는 작업 내용을 Task 단위로 분할하여 Executor에게 전달한다.
  6. executor들은 작업을 수행하고 결과를 저장하여 driver에게 제출한다.
  7. Driver 의 main()이 끝나거나 SparkContext.stop()이 호출된다면 Executor들은 중지되고 Cluster manager에 사용했던 자원을 반환한다.

기타 개념 정리

Deploy mode

cluster 사용시 driver 의 실행 위치를 지정한다.

  • Client mode: Driver가 Cluster 외부에 위차치할 때

  • Cluster mode: Driver가 Cluster 내부에 위치할 때

Job, Stage, Task

  • Job: stage의 집합. Application 에서 spark에 요청하는 일련의 작업
  • Stage: task의 집합
  • Task: 하나의 Executor에서 수행되는 최소 작업 단위
728x90
반응형
728x90
반응형

에러 메시지

Caused by: java.lang.AssertionError: assertion failed: Concurrent update to the commit log. Multiple streaming jobs detected for

 

원인

로그에 동시 업데이트 하기 때문에 발생

 

스파크 스트리밍에서 동일한 체크포인트 위치에 두 개 이상의 다른 스파크 작업이 업데이트 하려 할 때 발생한다.

이 때 스파크 설정의 checkpointLocation을 다른 위치로 사용하면 해결할 수 있다.

 

두 개의 다른 스파크 스트리밍 작업에서 checkpoint 위치를 다르게 한다.

      .option("checkpointLocation", checkpointPath1)
      .option("checkpointLocation", checkpointPath2)
728x90
반응형

+ Recent posts