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