실습 챕터

6-1. 스키마리스 데이터의 애드 혹 분석

스키마리스 데이터 수집하기

- API 활용

대화식 실행 환경의 준비

- Jupyter Notebook

- python pandas

Spark에 의한 분산 환경

- pyspark: 파이썬으로 대화식의 Spark 실행

- Spark는 마스터/슬레이브 형의 분산 시스템으로 클라이언트로부터 마스터에 명령을 보냄으로써 프로그램 실행

    - 클라이언트 = 드라이버 프로그램: 주피터와 조합 가능

    - 드라이버 프로그램은 로컬 노트북에서 실행 가능 => 실제 실행 환경은 보통 데이터 센터의 Spark 클러스터에 접속

- Spark의 데이터프레임은 pandas와 달리, 실제로 무언가의 처리를 요구할 때까지는 메모리상에서 DAG가 조림됨

    - RDD (Resilient Distributed Dataset): Spark의 로우 레벨 데이터 구조

데이터를 집계해서 데이터 마트 구축하기

- 데이터 마트를 만들 때의 선택지들

    - Spark에 ODBC/JDBC로 접속

    - MPP 데이터베이스에 비정규화 테이블 제작

    - 데이터를 작게 집약하여 CSV 파일에 출력

BI 도구로 데이터 시각화하기

- 탐색적 데이터 분석시에는 시행착오를 노트북에 축적하자

- 계속 모니터링해야 한다면 워크플로화 해서 자동화하자

- BI 도구: 데스크톱 형 vs 웹 형

    - 시각화는 이미지 처리, 필연적으로 데스크톱형의 도구가 우수

    - 네트워크에 의한 지연: 데이터 마트를 작게 만드는 것의 목적은 이런 문제를 제거하기 위한 것

    - 대시보드와 보고서 작성: 워크플로로 자동화 하려면 웹 형도구 필요

6-2. Hadoop에 의한 데이터 파이프라인

일일 배치 처리를 태스크화하기

1. 정기적으로 데이터 전송

2. 데이터 분석을 위해 Hive로 열 지향 스토리지 제작

3. Presto로 집계

[태스크 1] Embulk에 의한 데이터 추출

- 시간과 저장 공간을 멱등하게 처리

[태스크 2] Hive에 의한 데이터 구조화

- 열 지향 스토리지에 저장

- 파티셔닝을 통해 태스크 멱등성 확보

[태스크 3] Presto에 의한 데이터 집계

- 열 지향 스토리지에 저장된다면 장기간 집계도 고속화됨

- BI 도구에 읽어들임으로써 최종적인 데이터 파이프라인 완성

    - 파라미터를 교체해서 실행 자동화 가능

6-3. 워크플로 관리 도구에 의한 자동화

Airflow: 스크립트 형의 워크플로 관리

워크플로 정의

태스크 정의

워크플로를 터미널로부터 실행하기

스케줄러를 기동하여 DAG를 정기 실행하기

- 스케줄러: 데이터베이스의 상태를 정기적으로 점검하고 그 다음으로 실행 가능한 태스크를 찾음 -> 실행 가능한 태스크가 발견되면 워크 프로세스에 전달해 실행

- 오류로부터의 복구 염두한 설계

태스크가 소비하는 자원 제어하기

태스크의 분산 처리: 원격으로 워커 실행

- 데이터 처리의 실행은 Airflow 내에서 하는 것은 부적합

    - 데이터 처리는 분산 시스템에 맡기고 Airflow는 그 실행만 관리

Hadoop의 데이터 파이프라인을 실행하기

6-3. 클라우드 서비스에 의한 데이터 파이프라인

데이터 분석과 클라우드 서비스의 관계

- 클라우드 서비스의 장점

    - 자원 증감이 용이

    - 이용자는 설정 값만 신경 쓰면 됨

아마존 웹 서비스 (AWS)

- 기능마다 서비스가 나누어져 있어 이용자는 자신에게 필요한 것만 선택하고 연결함으로써 시스템 구축 가능

- 조합의 자유도가 높지만, 전체를 제대로 연결하려면 어느 정도 지식과 기술 요구

- 사용자가 직접 초기 설정하거나 워크플로 안에서 API를 서로 호출해야 함

    => 전체 구성을 직접 설계할 수 있음 (장점이자 단점)

- 빅데이터 관련 서비스 list

    - S3: 객체 스토리지

    - DynamoDB: NoSQL 데이터베이스

    - EMR: Hadoop&Spark

    - Athena: 쿼리 엔진 (Presto)

    - Elasticsearch: 검색엔진

    - Kinesis: 메시지 브로커

    - Kinesis Streams: 스트림 처리

    - Redshift: MPP 데이터베이스

    - QuickSight: BI 도구

구글 클라우드 플랫폼 (GCP)

- 애드 혹 데이터 분석과 처리 속도에 대한 요구가 큰 데이터 엔지니어 및 데이터 사이언티스트에게 유력한 선태기

- 빅데이터 관련 서비스 list

    - Cloud Storage: 객체 스토리지

    - Cloud Datastore: NoSQL 데이터베이스

    - Dataproc: Hadoop & Spark

    - Dataflow: 데이터 플로우 (배치, 스트리밍)

    - Colab: 노트북, 시각화

    - Pub/Sub: 메시지 브로커

    - BigQuery: 쿼리 엔진

    - Looker Studio: BI 도구

 

Amazon Redshift vs Google BigQuery

- Redshift

    - 전용 리소스 (dedicated resource): 스토리지와 계산 노드가 일체화 => 성능 안정적

- BigQuery

    - 공유 리소스 (shared resource): 수천 대의 하드 디스크에 데이터 분산 => 고속화 => 자신의 노드를 관리할 필요 없는 풀 매니지드형 서비스

트레주어 데이터

- 오픈소스의 스트리밍 형 전송 도구인 Fluentd와 벌크 형 전송 도구인 Embulk 개발사

- AWS, GCP와 달리 모든 서비스가 포함된 상태로 제공 (풀 매니지드형 서비스)

    - 외부 시스템과의 연계도 통합되어 있음

- 직접 컨트롤 할 수 있는 게 거의 없음 (장점이자 단점)

- 빅데이터 관련 서비스 list

    - Data Collection: 데이터 수집(스트리밍, 벌크)

    - Data Set Management: 분산 스토리지, 구조화 데이터

    - Data Processing: 쿼리 엔진 (Hive, Presto)

    - Data Delivery and Activation: ETL 프로세스

    - Treasure Workflow: 워크플로 관리

    - Treasure Reporting: BI 도구

    - DigDag: 선언형의 워크플로 관리

 

5-1. 워크플로 관리

[기초 지식] 워크플로 관리: 데이터의 흐름을 일원 관리하기

- 워크플로 관리(workflow management): 기업 내의 정형적인 업무 프로세스(신청, 승인, 보고 등)와 같이 정해진 업무를 원할하게 진행하기 위한 구조

    - 매일 매일의 태스크를 관리하는 구조가 정기적인 배치 처리 실행에도 유용하기 때문에 데이터 처리 현장에서도 자주 이용

- 일반적인 데이터 워크플로 관리:

    - 태스크는 정해진 스케줄에 따라 자동으로 실행

    - 무언가 비정상적 일이 발생한 경우에는 사람이 개입하여 문제 해결

워크플로 관리 도구

- 워크플로 관리 도구의 주요 역할: 

    - 정기적으로 태스크를 실행

    - 비정상적인 상태를 감지하여 그것에 대한 해결

- 대표적인 오픈소스 워크플로 관리 도구: Airflow, Digdag, Oozie

 

워크플로 관리 도구와 태스크

- 태스크(Task): 실행되는 개별 데이터 처리 단위

 

기본 기능과 빅데이터에서 요구되는 기능

- 워크플로 관리 도구가 필요한 이유: 태스크 실행에 실패할 수 있기 때문

- 아래 기능이 필요 (모든 태스크를 일원 관리하기 쉽게 해야 함)

    - 태스크를 정기적인 스케줄로 실행하고 결과 통지

    - 태스크 간의 의존 관계 정하고 정해준 순서대로 빠짐없이 실행

    - 태스크 실행 결과를 보관하고, 오류 발생 시에는 재실행할 수 있도록

 

선언 형과 스크립트 형

선언형(Declarative): XML, YAML 등의 서식으로 워크플로 기술

    - ex. Oozie

    - 미리 제공된 기능만 이용

    - 누가 작성해도 동일한 워크플로가 되기 때문에 유지 보수성이 높아짐

스크립트형 (Scripting): 스크립트 언어(ex. python)로 워크플로를 정의

    - ex. Airflow

    - 유연함: 태스크 정의를 프로그래밍할 수 있음

- 데이터 수집 과정에서는 스크립트 형의 도구를 사용하여 유연하게 워크플로를 조립하고, 데이터가 모아지면 정형적인 처리만 하게 되므로 이후에는 선언형 도구를 사용할 수 있다

오류로부터의 복구 방법 먼저 생각하기

빅데이터를 취급하고 있으면 다양한 오류가 발생

- 미리 예기치 못한 오류가 발생할 가능성을 고려하여 오류 발생 시의 대처 방법을 결정해두는 것이 중요

 

복구와 플로우의 재실행

- 수작업에 의한 복구를 전제한 태스크 설계

    - 오류로부터 자동 회복할 수 있다는 점은 고려하지 않는 것이 좋다 (오류의 종류는 수많기 때문에 전부 대응하는 것은 불가능)

- 플로우: 일련의 태스크

- 복구의 기초

    - 각 플로우 실행시 날짜를 파라미터화 한다

    - 동일 플로우에, 동일 파라미터를 건넬 시 동일한 태스크가 실행될 수 있다 => 플로우가 도중에 실패해도 나중에 동일 파라미터로 재실행 가능

 

워크플로의 버전 관리

- 복잡화된 데이터 파이프라인의 구축은 더 이상 시스템 개발고 ㅏ다른 분야가 아니기 대문에 소프트웨어 개발 분야에서 연마되어 온 버전 관리 기법을 도입하는 것을 추천 (Git)

 

태스크를 되도록 작게 유지하기

- 큰 태스크는 나누어 적당히 작은 복수의 태스크로 플로우를 구성하자

    - 문제가 발생해도 도중에 재개할 수 있음

 

재시도

- 여러 차례 반복하는 오류는 자동화

- 오류의 원인을 그때마다 조사하여 대책 마련

 

백필

- 일정 기간의 플로우를 연속해서 실행하는 구조

- 대량의 태스크를 실행할 때에는 성능상의 주의가 필요

    - 테스트 삼아 조금씩 백필 실행

 

 

멱등한 조작으로 태스크를 기술하기

- 멱등성: 동일한 태스크를 여러 번 실행해도 동일한 결과가 된다

    - 재실행의 안전성을 확보하는 데에 가장 중요

    - 태스크를 도중까지 실행하다 실패했을 때 도중 경과가 남아있으면, 태스크 재실행에 의해 데이터가 혼재 될 수 있음

    - 각 태스크는 원칙적으로 '마지막까지 성공'하거나 '실패하면 아무것도 남지 않음' 이 둘 중 하나만 존재해야 함

        - '도중가지 성공'이라는 어정쩡한 상황은 허가하지 않아야 함

 

원자성 조작

- 원자성 조작(atomic operation): 각 태스크가 시스템에 변경을 가하는 것을 한 번만 할 수 있도록 하는 것

- 워크플로에 포함된 태스크를 모두 원자성 조작으로 구현함으로써 재시도의 안전성을 높일 수 있음

- 원자성 조작이 문제를 야기하는 경우:

    - 원자성 조작 직후에 문제가 발생하면, 워크플로 관리 도구에서 이를 오류로 여겨 재시도 하는 경우

    -> 재시도로 인한 중복 발생

 

멱등한 조작 - 추가와 치환

- 멱등한 조작(idempotent operation): 동일한 태스크를 여러 번 실행해도 동일한 결과가 되도록 하는 것

    - 안정성을 확보하는 가장 확실한 방법

- 위 예시에서 멱등한 조작이면 재실행 해도 중복 발생 안함

- 원칙적으로는 항상 데이터를 덮어써야 함

    - 추가 (append)는 데이터가 중복되지만, 치환 (replace, overwrite)은 반복해도 결과가 변하지 않음

- 태스크에 부여된 파라티러를 잘 이용해 여러 번 실행해도 항상 치환이 되도록 설계

 

멱등한 추가

- 테이블 파티셔닝하여, 파티션 단위로 치환하도록 한다

- 태스크를 멱등으로 구성하는 것이 어렵다면, 그것을 포기하고 원자성을 지닌 추가로 운용

    - 오류 발생 시, 수작업으로 복구

 

원자성을 지닌 추가

- 하나의 테이블에 몇 번이고 데이터를 써넣을 때가 있음

    - 이 경우 추가를 반복하지 말고 중간 테이블을 만들어 처리한 후, 마지막에 목적 테이블에 한 번에 추가하는 것이 안전

 

워크플로 전체를 멱등으로 하기

- 데이터 파이프라인을 안정적으로 운용하기 위해서는 거기에 포함된 태스크나 플로우를 가능한 한 멱등으로 해야 함

- 데이터 마트를 구축하는 플로우에서도 되도록 추가는 삼가고 테이블마다 치환

    - 멱등한 태스크는 실패시 안전하게 재실행할 수 있음

태스크 큐: 자원의 소비량 컨트롤하기

- 워크플로 관리 도구에서 요구되는 커다란 역할 중 하나가 부하 컨트롤

- 병렬화가 필요한 경우

    - 너무 대량의 태스크를 동시 실행하면 서버에 과부하가 걸리므로 어느 정도 제한을 해야 함

- 잡 큐 (job queue) (= 태스크 큐(task queue)) 구조

    - 모든 태스크는 일단 큐에 저장되고 일정 수의 워커 프로세스가 그것을 순서대로 꺼내면서 병렬화가 실현

병목 현상의 해소

- 워크플로 실행 시 자주 발생하는 문제 (서버의 내부적인 요인)

    1. CPU 사용률 100% -> CPU 코어 수를 늘린다. 서버를 증설한다.

    2. 메모리 부족 -> 메모리를 증설한다. 스왑 디스크를 추가한다. 태스크를 작게 분할한다.

    3. 디스크 넘침 -> 각 태스크가 임시 파일을 삭제하고 있는지 확인한다. 디스크를 증설한다.

    4. 디스크 I/O의 한계 -> SSD 등의 고속 디스크를 사용한다. 여러 디스크로 분산한다.

    6. 네트워크 대역의 한계 -> 고속 네트워크를 사용한다. 데이터의 압축률을 높인다.

    7. 통신 오류나 타임 아웃 -> 시스템 상의 한계일 가능성이 있다. 서버를 분리한다.

- 서버 외부 요인이 원인인 병목 현상은 문제를 제거할 수 없다.

 

태스크 수의 적정화 - 너무 크거나 너무 작지 않은 정도로 잘 분할하기

- 작은 태스크를 자주 실행하면 오버헤드만 커짐

- 태스크가 너무 클 경우에는 나누고, 너무 작을 경우에는 하나로 모음으로써 각 태스크가 적절한 크기가 될 수 있도록 조정

 

 

5-2. 배치 형의 데이터 플로우

MapReduce의 시대는 끝났다 - 데이터 플로우와 워크플로

- 데이터 플로우(data flow): 다단계의 데이터 처리를 그대로 분산 시스템 내부에서 실행 (워크플로와 구분해서 사용)

MapReduce의 구조

- 과거 빅데이터의 대표적인 기술이었지만 이제 새롭게 사용되는 일은 없어짐

    - Google: MillWheel
    - Hadoop: Tez
- MapReduce의 개념
    1. Split: 분산 처리를 위해 데이터 파일을 일정 크로 나눔
    2. Map: 분할된 데이터를 처리 (함수 적용 ex. count)
    3. Reduce: 분산된 결과를 모아서 집계

- 하나의 사이클이 끝나지 않으면 다음 처리로 이동하지 못함

    - 하나의 사이클에서 다음 사이클로 이동할 때까지의 대기 시간이 긴 단점

- 애드 혹 분석에서는 실현 어려움

 

MapReduce를 대신할 새로운 프레임워크 - DAG에 의한 내부 표현

- DAG(Directed Acyclic Graph) 데이터 구조로 새로운 프레임워크에서 사용

    - 데이터 플로우에서 실행해야 할 일련의 태스크를 DAG에 의핸 데이터 구조로 표현

    - 화살표는 태스크 실행 순서

    - 의존 관계를 유지하며 실행 순서를 알맞게 정하면 모든 태스크를 빠짐없이 완료할 수 있음

    - DAG는 시스템 내부적인 표현으로 이용자가 존재를 의식할 일 거의 없음: 데이터 플로우에 국한되지 않고, Hive on Tez나 Presto같은 쿼리 엔진에서도 DAG 구조 채택

Spark에서의 DAG

- Spark과 같은 데이터 플로우 프레임워크서는 프로그래밍 언어를 사용하여 DAG를 직접 조립

    - 처리 내용이 복잡해지면 DAG도 그만큼 복잡해짐

- 지연 평가 (lazy evaluation): 프로그램의 각 행은 실제로는 DAG 데이터 구조를 조립할 뿐, 후에 실행 결과를 요구할 때 데이터 처리가 시작됨

    => 내부 스케줄러가 분산 시스템에 효과적인 실행 계획을 세울 수 있음

데이터 플로우와 워크플로를 조합하기

- 태스크를 정기적으로 실행하거나, 실패한 태스크를 기록하여 복구하는 것은 데이터 플로우에서 할 수 없음. 워크플로 관리 필요

    - 데이터 플로우의 프로그램도 워크플로의 태스크로 고려할 수 있음

- 분산 시스템 외부와 데이터를 주고받을 경우도 워크플로 안에서 실행하는 것이 바람직

데이터를 읽어들이는 플로우

- 워크플로 조합

    - Task 1: 데이터 소스에서 분산 스토리지로 벌크 전송

    - Task 2: 데이터 플로우로 필요한 연산, 분산 스토리지에서 실행

데이터를 써서 내보내는 플로우

- 워크플로 조합

    - Task 1: 데이터 플로우를 통해 CSV 같이 취급하기 쉬운 형식으로 변환

    - Task 2: 외부로 전송

 

데이터 플로우와 SQL을 나누어 사용하기

- 데이터 웨어하우스 파이프라인 (SQL을 MPP 데이터베이스에서 실행)

    - 데이터 플로우: DB에서 분산 스토리지로 벌크 전송 -> 데이터 웨어하우스로 로드

    - SQL: 배치 처리 (시각화)

- 데이터 마트 파이프라인 (쿼리 엔진은 분산 시스템에서 실행)

    - 데이터 플로우: DB에서 분산 스토리지로 벌크 전송

    - SQL: 쿼리 엔진으로 배치 처리 (마트 제작)

대화식 플로우 - 애드혹 분석의 파이프라인

- 데이터 처리를 수작업으로 시행하므로 워크플로는 필요하지 않음

- 구조화되어 있지 않은 데이터를 애드 혹 분석시, 데이터 플로우가 매우 유용

- 구조화된 데이터는 쿼리 엔진을 사용

 

5-3. 스트리밍 형의 데이터 플로우

배치 처리와 스트림 처리로 경로 나누기

- 배치 처리 중심의 데이터 파이프라인의 결점은 데이터가 분석할 수 있게 될 때까지 시간이 걸림

- 실시간: 이벤트 발생에서 몇 초 후에는 결과를 알 수 있는 것

- 실시간성이 높은 데이터 처리 시스템 예

    - 시스템 모니터링

    - 로그 관리 시스템

    - 복합 이벤트 처리 (Complex Event Processing, CEP)

- 스트림 처리 (streaming processing): 분산 스토리지를 거치지 않고 처리를 계속하는 것

- 스트림 처리는 실시간성이 우수하지만, 과거 데이터를 취급하는 데에는 부적합

배치 처리와 스트림 처리 통합하기

- 배치 처리: 먼저 데이터가 있고, 그것을 작게 나눠서 DAG에 흘려 넣음 (유한 데이터 bounded data)

- 스트림 처리: 끊임없이 데이터가 생성되며, 그것이 DAG 안에 흘러들어옴 (무한 데이터 unbounded data)

- DAG를 사용한 데이터 플로우에서는 배치 처리와 스트림 처리를 동일하게 프로그래밍하는 것이 가능

Spark 스트리밍의 DAG

- 데이터를 읽고 쓰는 초기화 부분(socketTextStream("localhost", 9999))에 차이가 있을 뿐, 데이터 처리 중심부 (Map -> Reduce)는 동일

- 배치 처리는 데이터 처리가 끝나면 종료되는데, 스트림 처리는 프로그램을 정지할 때까지 끝없이 실행

 

스트림 처리의 결과를 배치 처리로 치환하기

- 스트림 처리의 두 가지 문제

    1. 잘못된 데이터 수정하기 어려움

    2. 늦게 전송된 데이터 취급

- 배치 처리를 실행해 스트림 처리의 문제를 대처

    - 스트림 처리 결과는 배치 처리 결과가 나올 때까지의 잠정 값으로 이용

람다 아키텍처: 배치 레이어, 서빙 레이어, 스피드 레이어

- 배치 레이어: 과거 데이터를 장기적인 스토리지에 축적하고, 여러 번이고 다시 집계

    - 대규모 배치 처리를 실행할 수 있는 반면, 1회 처리에는 긴 시간 걸림

- 서빙 레이어: 응답이 빠른 데이터베이스 설치

    - 배치 뷰: 서빙 레이어에서 얻어진 결과

        - 정기적으로 업데이트되지만, 실시간 정보를 얻을 수 없음

- 스피드 레이어: 스트림 처리

    - 실시간 뷰: 배치 뷰가 업데이트될 동안까지 이용되고 오래된 데이터는 순서대로 삭제

- 장점: 실시간 뷰의 결과는 나중에 배치 뷰로 치환

- 단점: 나쁜 개발 효율

    - 스피드 레이어와 배치 레이어 모두 똑같은 처리를 구현하는 비효율

 

카파 아키텍처

- 카파 아키텍처: 람다 아키텍처를 단순화함

- 배치 레이어, 서빙 레이어 제거하고 스피드 레이어만 남김

- 메시지 브로커의 데이터 보관 기간을 충분히 길게 함

    - 스트림 처리를 멱등으로 구현하여, 과거 데이터 보정(백필)을 가능하도록 함

- 단점: 부하가 높아짐

    - 클라우드 서비스 보급에 의해 자원 확보가 어렵지 않게 되었으므로 '스트림 처리르 다시 하는 것이 간단하다'는 게 카파 아키텍처의 철학

 

아웃 오브 오더의 데이터 처리

- 아웃 오브 오더(out of order) 데이터: 늦게 도달하는 메시지, 프로세스 시간과 이벤트 시간의 차이

 

원래 데이터의 모습은 '이벤트 시간'으로 얻을 수 있다

- 이벤트 시간으로 집계한 것이 올바른 결과

이벤트 시간 윈도잉

: 이벤트 시간에 의해 윈도우를 나누는 것

- 과거 이벤트 상태를 보관하면서, 데이터가 도달할 때마다 해당하는 윈도우를 재집계할 필요 있음

- 일정 시간 늦게 온 데이터는 무시

4-1. 벌크 형과 스트리밍 형의 데이터 수집

데이터 전송의 두 종류

- 벌크 형

- 스트리밍 형

객체 스토리지와 데이터 수집

빅데이터는 단지 수집만 해서는 안 되고 나중에 처리하기 쉽도록 준비해 둘 필요가 있다

- 대략 1MB ~ 1GB

데이터 수집: 수집한 데이터를 가공하여 집계 효율이 좋은 분산 스토리지를 만드는 일련의 프로세스

- 데이터 수집

- 구조화 데이터 작성

- 분산 스토리지 장기적 저장

벌크 형의 데이터 전송: ETL 서버의 설치 필요성

벌크 형 (전통적인 데이터 웨어하우스에서 사용)

- 데이터베이스, 파일 서버 또는 웹 서비스 등에서 각각의 방식 (SQL, API 등)으로 정리해 데이터를 추출

- 원래 데이터가 처음부터 분산 스토리지에 저장되어 있는 것이 아니라면 데이터 전송을 위한 ETL 서버를 설치

 

파일 사이즈의 적정화는 비교적 간단하다

- 하루마다 또는 1시간 마다의 간격으로 정기적인 실행을 하므로 그동안 축적된 데이터를 하나로 모아서 전송 (=> 파일 사이즈 결정)

- 너무 많은 양의 데이터를 한꺼번에 전송하려 하는 것은 위험: 너무 큰 데이터라면 전송 도구에서 나눌 수 있음

    - 한 번의 태스크 실행이 커지지 않도록 조정

 

데이터 전송의 워크플로 - 워크플로 관리 도구와의 친화성

- (스트리밍은 재실행이 어려운 방면) 문제가 발생했을 때 여러 번 데이터 전송을 재실행할 수 있다는 점이 벌크 형의 장점

    - 워크플로 관리도구(ex. Airflow) 와 궁합이 뛰어남 

 

스트리밍 형의 데이터 전송

- 계속해서 전송되어 오는 작은 데이터를 취급하기 위한 전송 방식

    - 지금 바로 생성되어 아직 어디에도 저장되지 않은 데이터는 그 자리에서 바로 전송할 수밖에 없음

- 예: '웹 브라우저', '모바일 앱', 센서 기기 등의 '디바이스'에서의 데이터 수집

    - 다수의 클라이언트에서 계속해서 작은 데이터가 전송됨 (= 메시지 배송)

- 메시지 배송 시스템은 전송되는 데이터양에 비해 통신을 위한 오버헤드가 커짐

    => 이를 처리하는 서버는 높은 성능을 요구

- 메시지 저장 방식

    1. NoSQL 데이터베이스 사용

    2. 메시지 큐, 메시지 브로커 등의 중계 시스템 사용

 

웹 브라우저에서의 메시지 배송

- 로그 수집 소프트웨어 자주 사용

- 웹 이벤트 추적: 자바스크립트 사용

모바일 앱으로부터의 메시지 배송

- 메시지 배송 방식이 웹 브라우저와 동일

- 백엔드 서비스 (Mobile Backend as a Service)를 이용할 수도 있음

- 모바일용 SDK를 사용하기도 함

- 데이터가 중복될 가능성도 높아, 중복 제거 구조가 필요할 수도

디바이스로부터의 메시지 배송

- MQTT (MQ Telemetry Trnasport)

    - Topic, 구독

메시지 배송의 공통화

- 클라이언트 (Client): 메시지가 처음 생성되는 기기

- 프론트 엔드 (Frontend): 해당 메시지를 먼저 받는 서버

    - 프론트 엔드의 역할: 클라이언트와의 통신 프로토콜을 제대로 구현하는 것

- 메시지 브로커: 프론트 엔드가 받은 메시지를 전송 받음

    - 이후 분산 스토리지에 데이터 저장

- 역할 분리를 통해 프론트 엔드는 단지 데이터를 받는 것에만 전념하고 거기에서 그 이후의 어려운 문제에 대해서는 백 엔드에 존재하는 공통 시스템에 맡길 수 있음

4-2. [성능 x 신뢰성] 메시지 배송의 트레이드 오프

메시지 브로커 - 스토리지의 성능 문제를 해결하는 중간층의 설치

- 대량의 메시지를 안정적으로 받기 위해서는 빈번한 쓰기에도 견딜 수 있도록 성능이 매우 높고 필요에 따라 성능을 얼마든지 올릴 수 있는 스토리지 필요

    - 분산 스토리지가 그런 성격을 갖고 있지 못함

- 메시지 브로커(Message Broker): 데이터를 일시적으로 축적하는 중간층

    - 오픈 소스: Apache Kafka

    - 클라우드 서비스: Amazon Kinesis

 

푸시 형, 풀 형 - 확장성 향상과 파일 사이즈의 적정화

메시지 브로커는 높은 빈도의 데이터 쓰는 것에  최적화 됨 + 여러 대 노드에 부하 분산하여 성능을 끌어올릴 수 있는 뛰어난 확장성 구현

- 푸시 (Push)형: 송신 측의 제어로 데이터를 보내는 방식

- 풀 (Pull)형: 수신 측의 주도로 데이터를 가져오는 방식

- 생산자 (Producer): 메시지 브로커에 데이터를 넣는(push) 것

- 소비자 (Consumer): 메시지 브로커로부터 데이터를 꺼내오는(pull) 것

    - 소비자는 메시지 브로커로부터 일정한 간격으로 데이터를 취함으로써 적당히 모아진 데이터를 분산 스토리지에 기록

 

메시지 라우팅

- 스트림 처리 (Stream Processing): 짧은 간격으로 차례대로 데이터를 꺼내서 처리하는 것

- 메시지 라우팅 (Message Routing): 메시지가 복사되어 데이터를 여러 경로로 분기시킨 것

    - 메시지 브로커에 써넣은 데이터는 복수의 다른 소비자가 읽을 수 있음

    - ex. 일부는 장애 감지에 사용 + 장기적인 데이터 분석을 위한 분산 스토리지에 저장

 

메시지 배송을 확실하게 실시하는 것은 어렵다 : 신뢰성 문제와 세 가지 설계 방식

- 신뢰성 문제: 모바일 회선과 같은 신뢰성이 낮은 네트워크에서는 반드시 메시지 중복이나 누락이 발생

- 메시지 처리 시스템의 설계 방식

    1. at most once: 메시지는 한 번만 전송. 그러나 도중에 전송에 실패해서 사라질 가능성 있음 (누락)

    2. exactly once: 메시지는 손실되거나 중복 없이 한 번만 전달

    3. at least once: 메시지는 확실히 전달. 단 같은 것이 여러 번 전달될 가능성 있음 (중복)

 

at most once

- 무슨 일이 일어나도 절대로 메시지를 다시 보내지 않음

- 그러나 대개는 데이터 결손을 피하고자 재전송(retransmission)이 이루어짐 - 재전송하는 시스템에서는 at most once를 보장하는 것이 어려움

exactly once

- 양 쪽 통신 내용을 보장하려면 그 사이를 중계하는 coordinator의 존재가 필수

    - 송신 측과 수신 측 모두 서로의 정보를 코디네이터에게 전달함으로써 문제가 발생한 경우에는 코디네이터의 지시에 따라 해결

- 근본적인 두 가지 문제 

    1. 분산 시스템에서는 coordinator가 항상 존재한다고 가정할 수 없음

        - coordinator와의 통신이 끊기는 경우도 있고, coordinator 자체가 정지될 수도 있음

        - coordinator 부재 (장애)의 경우 어떻게 할 것이가에 대한 합의 필요 => 분산 시스템 설계에 어려움 가중

    2. coordinator 의 판단에만 의존하면 시간이 너무 소요됨

 

at least once: 중복 제거는 사용자에게 맡긴다

- 위의 이유로, 대부분 메시지 배송 시스템에서는 coordinator를 도입하지 않고 at least once로 구축

    - 중복 제거는 메시지 소비자부터의 사용자에게 맡기고 있음

 

중복 제거는 높은 비용의 오퍼레이션

중복 제거의 여러 방법들과 철학

오프셋을 이용한 중복 제거

- 메시지가 중복되어도 같은 파일의 같은 장소 덮어쓰기

- 벌크 형의 데이터 전송과 같이 데이터 양이 고정된 경우에 잘 작동

- 스트리밍 형식의 메시지 배송에서는 채택 거의 안함

고유 ID에 의한 중복 제거

- 모든 메시지에 UUID (Universally Unique IDentifier) 지정

- 메시지가 늘어남에 따라 ID가 폭발적으로 증가 - 이에 대한 관리 필요

    - 과거 전송된 모든 ID를 기억하는 것은 비현실적이고, ID를 파기하면 늦게 도착한 메시지가 중복됨

    - 현실적인 타협: 최근 ID만 기억하고 (최근 n시간) 이후 중복은 허용

        - 중복은 일시적인 통신 오류 때문이므로 이를 제거하면 99%의 신뢰도 달성

종단간(End to End)의 신뢰성

- 빅데이터의 메시지 배송에서는 신뢰성보다는 '효율'쪽이 중시됨

    - 중간 경로에 'at least once'를 보장하는 한편, 중복 제거는 하지 않는 것이 표준적인 구현

- 이론상 스트리밍에서 중복 제거가 완벽히 되려면, 송신과 수신 양 쪽 모두 중복제거를 잘 해야 한다

    - 매우 어려움

- 중간 경로를 모두 at least once로 통일하고 클라이언트 상 모든 메시지에 고유 ID를 포함하도록 하여 경로 말단에서 중복 제거를 실행하자 (일반적인 설계)

경로 말단에서 고유 ID를 사용한 중복 제거의 방법 - NoSQL 데이터베이스 vs SQL

1. 분산 스토리지로 NoSQL 데이터베이스 이용

    - Cassandra, Elasticsearch 등은 데이터 쓸 때 고유 ID를 반드시 지정 => 동일한 ID의 데이터는 덮어씀

2. SQL로 중복 제거 (SELECT DISTINCT ...)

    - 대규모 데이터 처리이므로 메모리 실행은 거의 불가능하고 Hive같은 배치형 쿼리 엔진에서 실행

 

데이터 수집의 파이프라인 - 장기적인 데이터 분석에 적합한 스토리지

데이터 수집 파이프라인

이처럼 일련의 프로세스를 거친 다음, 마지막으로 데이터를 구조화해서 열 지향 스토리지로 변환

=> 장기간 데이터 분석에 적합한 스토리지 완성

 

중복을 고려한 시스템 설계 - 빅데이터 시스템에 있어서의 '중복'에 대한 사고방식

- 일반적으로 스트리밍 형의 메시지 배송에서는 중간에 명시적으로 중복 제거 방식을 도입하지 않는 한 항상 중복의 가능성이 있다고 생각하는 것이 좋다

    - 빅데이터 시스템은 매우 높은 성능을 요구하기 때문에 아주 작은 중복은 무시하는 경향

    - 중복이 있어도 문제가 되지 않는 시스템을 설계하자

- 신뢰성이 중시되는 경우에는 스트리밍 형의 메시지 배송은 피하는 것이 가장 좋다

    - ex. 과금에 필요한 데이터 (오차가 허용되지 않음)

        - 트랜잭션 처리를 지원하는 데이터베이스에 애플리케이션이 직접 기록

        - 이후 벌크 형의 데이터를 전송 함으로써 중복도 결손도 확실하게 피함

 

4-3. 시계열 데이터의 최적화

스티리밍 형의 메시지 배송에서는 '메시지가 도착할 때까지의 시간 지연'이 문제

프로세스 시간과 이벤트 시간

- 이벤트 시간 (event time): 클라이언트 상에서 메시지가 생성된 시간

- 프로세스 시간 (process time): 서버가 처리하는 시간

- 데이터 분석의 대상이 되는 것은 '이벤트 시간'

 

프로세스 시간에 의한 분할과 문제점 - 최대한 피하고 싶은 풀 스캔

- 늦게 도달하는 데이터가 있다는 것은 과거 집계 결과가 매일 조금씩 바뀜

   - 보다 실태에 가까운 집계 결과를 얻기 위해서는 '이벤트 시간'보다 며칠 지난 시점에서 소급해 집계 해야 함

- 이벤트 시간으로 데이터가 정렬되어 있지 않으면, 모든 데이터를 로드(풀 스캔)해야만 이벤트 시간을 검색할 수 있음

 

시계열 인덱스 - 이벤트 시간에 의한 집계의 효율화 1

- 시계열 인덱스 (time-series index): 이벤트 시간에 대해 인덱스를 만드는 것

    - ex. Cassandra는 시계열 인덱스를 사용하는 데이터베이스

- 장점: 매우 짧은 범위의 특정 시간에 맞춘 데이터 집계 빠르게 실행 가능

- 단점: 장기간에 걸쳐 대량의 데이터를 집계하는 경우에는 비효율적

조건절 푸시 다운 - 이벤트 시간에 의한 집계의 효율화 2

- 배치 처리를 통해, 이벤트 시간으로 데이터 정렬 후 열 지향 스토리지로 변환

- 조건절 푸시 다운(predicate pushdown): 정렬된 데이터의 칼럼 단위 통계 정보를 이용한 최적화

    - 각 칼럼의 최솟값, 최댓값을 메타 정보로 저장

이벤트 시간에 의한 분할 - 테이블 파티셔닝, 시계열 테이블

- 시계열 테이블 (time-series table): 시간을 이용하여 물리적으로 파티셔닝한 테이블

    - 이벤트 발생 시간을 파티션으로 하여 새로운 데이터가 들어올 때 (늦게 올 때)마다 추가

- 잠재적 문제: 시계열 테이블을 구성하는 각 파티션에 매일 조금씩 데이터가 추가됨

    => 분산 스토리지에 대량의 작은 파일이 만들어지고 점차 쿼리 성능이 악화됨

    => 작은 데이터를 효율적으로 추가할 수 있는 분산 데이터베이스를 사용하거나 너무 오래된 데이터는 버려야 함

데이터 마트를 이벤트 시간으로 정렬하기

- 데이터 마트 제작시 이벤트 시간에 의한 정렬

    - 수집 단계에서는 프로세스 시간으로 저장

- 항상 최적의 데이터를 유지할 수 있는 좋은 방법

 

모바일 기기의 시계는 미쳤다(!?)

- 시간이 이상한 데이터는 가급적 이른 단계에서 찾아 제외

    - 집계 효율에 문제 일으킬 수도

 

4-4. 비구조화 데이터의 분산 스토리지

NoSQL 데이터베이스의 몇 가지 특징

참고: https://db-engines.com/en/ranking

[기본 전략] NoSQL 데이터베이스에 의한 데이터 활용

- 객체 스토리지 상의 파일은 교체하기 어려움

- 쓰기 빈도가 높은 데이터는 RDB로 저장하고, 정기적으로 스냅샷을 하거나 다른 '분산 데이터베이스'에 저장하도록 해야 함

- 객체 스토리지는 '데이터를 기록하고 곧바로 활용'하는 것은 부족

    - 실시간 집계와 검색에 적합한 데이터 저장소가 필요

- NoSQL 데이터베이스: 특정 용도에 최적화된 데이터 저장소

분산 KVS: 디스크로의 쓰기 성능 높이기

- 분산 KVS (Distributed Key-Value Store): 모든 데이터를 key-value 쌍으로 저장하도록 설계된 데이터 저장소

    - (객체 스토리지도 넓은 의미에서는 분산 KVS의 일종이지만, 여기서는 좀 더 '작은 데이터'를 가정)

- 작동 방식    

    1. 모든 데이터에 고유의 키를 지정 - 부하 분산을 위해 이용

    2. 키가 정해지면 그 값을 클러스터 내의 어느 노드에 배치할 것인지 결정 - 부하를 균등 분산하고 노드를 증감하여 클러스터 성능 변경

Amazon DynamoDB

- 데이터의 읽기 쓰기에 지연이 발생하면 곤란한 애플리케이션에 유용

- P2P형: 모든 노드가 대등한 관계

    - 참고) 마스터/슬레이브형: 1대의 마스터가 전체를 관리

- Amazon EMR, Amaozon Redshift 등과 결합함으로써 Hive 배치 처리 및 데이터웨어하우스에 데이터 전송 등이 가능

- DynamoDB Streams로 실시간 스트림 처리도 가능

 

NoSQL 데이터베이스 자체는 대량의 데이터를 집계하는 기능이 없는 것이 많아 데이터 분석을 위해서는 외부로 데이터 추출 해야 함

 

[기초 지식] ACID, CAP

ACID: 트랜잭션 처리에 요구되는 4가지 성질 (일반적인 RDB는 이들을 충족)

- Atomicity: 원자성

- Consistency: 일관성

- Isolation: 독립성

- Durability: 내구성

 

CAP: 분산 시스템은 ACID 특성을 만족하는게 어려워, 그 한계로 제창 (일반적으로 분산 시스템에서는 다음 3가지를 동시 충족시킬 수 없어 어느 하나가 희생될 수 있음)

- Consistency: 일관성

- Availability: 가용성

- Partition-Tolerance: 분단 내성

 

결과 일관성

- NoSQL 데이터베이스 일부는 CAP의 '일관성'이나 '가용성' 중 하나 선택

- 일관성 우선하고 가용성 포기 = 단시간의 장애 발생 수용

- 가용성을 우선하고 일관성을 포기 = 오래된 데이터 읽을 수 있지만, 써 넣은 데이터를 바로 읽을 수 없는 경우 존재

 

 

와이드 칼럼 스토어: 구조화 데이터를 분석해서 저장하고

- 와이드 칼럼 스토어 (wide-column store) 분산 KV를 발전시켜 2개 이상의 임의의 키에 데이터를 저장할 수 있도록 한 것

    - Goggle Cloud Bigtable, Apache HBase, Apache Cassandra

- 행 추가 뿐만 아니라 칼럼 추가도 얼마든지 할 수 있음 (이론 상 수억의 칼럼 만들 수 있음)

    - 가로, 세로 2차원 (또는 그 이상)의 데이터 구조

 

Apache Cassandra

- 별도의 쿼리 언어 존재 (CQL)

- 테이블의 스키마를 결정하여 구조화 데이터만 취급

- 동일한 키를 가진 레코드가 존재하면 INSERT INTO로 덮어쓸 수 있음 

- P2P 형의 분산 아키텍처: 저장한 키에 의하 결정한 노드에 해당 키와 관련된 모든 값을 저장

    - 다수의 독립적인 키가 있는 경우 처리를 잘 분산

- 데이터를 집계하는 데에는 적합하지 않음: 집계를 위해서는 분산된 모든 노드에서 데이터를 모아야 함

    - Hive, Presto, Spark 등의 쿼리 엔진 모두 Cassandra로부터의 로드에 대응

도큐먼트 스토어: 스키마리스 데이터 관리하기

- 데이터 처리의 유연성이 목적

- JSON처럼 복잡하게 뒤얽힌 스키마리스 데이터를 그대로의 형태로 저장

- 장점: 스키마를 정하지 않고 데이터 처리할 수 있음

    - 외부 시스템의 데이터 및 로그 저장 등에 적합

- 최근 RDB에서도 도큐먼트 스토의 기능이 포함됨

MongoDB

- 성능을 우선하여 신뢰성을 희생

- 그 자체는 대량의 데이터 집계에 적합하지 않음. 분석이 목적인 경우에 쿼리 엔진으로부터 접속

 

검색 엔진: 키워드 검색으로 데이터 검색

- 텍스트 데이터를 전문 검색하기 위해 '역 색인 (inverted index)'을 만들어 사용

    - 데이터를 기록하는 리소스는 커지지만, 그 덕분에 키워드 검색이 훨씬 고속화됨

- 역 색인(inverted index): 텍스트에 포함된 단어를 분해하고 어떤 단어가 어떤 레코드에 포함되어 있는가 하는 인덱스를 미리 만들어 둠으로써 검색을 고속화

- NoSQL이 index 제작을 최소화하는 반면, 검색 엔진은 index를 적극적으로 제작

    - 검색 엔진은 데이터 집계에 적합

    - 비정상적인 상태 감지 및 보안 체크, 고객 서포 등 민첩성이 요구되는 용도에 사용

    - (장기적 데이터 축적보다는) 실시간 집계 시스템의 일부로 이용

 

Elasticsearch

- 오픈소스 검색 엔진

- ELK 스택

    - 검색엔진 소프트웨어: Elasticsearch

    - 로그 수집 소프트웨어: Logstash

    - 시각화 소프트웨어: Kibana

Splunk

- 비정형 데이터(웹 로그, JSON 파일 등)에 특화

+ Recent posts