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 파일 등)에 특화