시작하며

4장은 빅데이터를 축적하는 방법을 다룬다. 데이터의 전송 방식에 따라 벌크(bulk)와 스트리밍(streaming)으로 나뉘며, 각각의 특성과 신뢰성 보장 방법, 그리고 NoSQL 데이터베이스의 역할을 살펴본다.

1. 벌크와 스트리밍 데이터 전송

데이터 수집이란 수집한 데이터를 가공하여 집계 효율이 좋은 분산 스토리지를 만드는 과정을 말한다.

빅데이터를 저장하기 위한 저장소로 객체 스토리지(object storage)를 많이 사용한다. 파일 스토리지와 다르게 객체 스토리지(object storage)는 여러 HW에 분산되어 평면(flat) 구조로 저장되고, 고유 식별자를 비롯한 여러 메타 데이터를 가진 상태로 저장된다. 객체 스토리지를 도입하는 경우에는 네트워크 성능도 함께 고려해야 한다. 대표적인 스토리지로 HDFS, AWS S3 등이 있다.

  • 다수의 하드웨어에서 분산 처리하므로 데이터의 양이 많을수록 유리하다.
  • 반면 소량의 파일을 자주 읽고 쓰는 경우, 통신 오버헤드가 크므로 오히려 불리하다.

(벌크형의 데이터 처리) 벌크형의 데이터는 적정한 크기의 태스크로 쪼개어 워크플로 관리 도구를 통해 실행한다. 태스크의 크기를 꾸준히 모니터링하면 디스크 풀 등 잠재적인 문제와 함께, 재수행을 수월하게 할 수 있는 장점이 있다. 여러 번 데이터를 재전송할 수 있다는 점은 데이터의 신뢰성을 확보하는 데 큰 도움이 된다.

(스트리밍 데이터의 처리) 각종 디바이스나 실시간성으로 생성되는 데이터의 경우에는 벌크형 도구로 모으는 것이 쉽지 않기 때문에 벌크의 경우와는 다른 별도의 처리 과정을 거친다. 이런 경우에는 분산 스토리지에 바로 쓰지 않고 메시지 큐(message queue)메시지 브로커(message broker) 등의 중계 시스템을 통한다.

  1. 웹브라우저 : 웹브라우저가 있는 경우는 전송 효율을 위해 서버상에 데이터를 축적해 두었다가 전송한다. Fluentd, Logstash 등 상주형 로그 수집 소프트웨어를 많이 사용한다. 축적된 파일을 수집하여 Kafka에 저장해 두었다가 컨슘하는 구조가 대표적이다.

  2. 모바일 앱 : 모바일 앱 역시 HTTP 프로토콜을 사용하는 클라이언트로서, 메시지 배송 방식은 웹브라우저와 동일하다. 다만 모바일 앱은 서버를 직접 마련하는 것이 아니라 MBaaS(Mobile Backend as a Service)와 같은 백엔드 서비스를 이용할 수 있다. 모바일 회선은 통신이 불안정하고 데이터 중복의 가능성이 높아 중복에 대한 대책이 마련되어야 한다.

  3. IoT 디바이스 : IoT 등의 디바이스는 여러 규격이 있지만 대표적으로 MQTT(Message Queuing Telemetry Transport) 프로토콜에 의한 배송이 있다. Pub/Sub 구조를 통해 특정 Topic을 구독하고 있는 Subscriber들에게 메시지가 뿌려진다.

Tip

MQTT(Message Queuing Telemetry Transport)

MQTT 브로커는 경량 메시징 프로토콜을 사용하는 메시지 브로커의 한 종류이다. IoT(Internet of Things) 환경에서 많이 사용되며, 네트워크 대역폭이 제한적이거나 연결이 불안정한 환경에서도 효율적으로 메시지를 교환할 수 있도록 설계되었다. 발행/구독(pub/sub) 모델을 기반으로 작동한다.

대표적인 MQTT 제품은 다음과 같다.

  1. Mosquitto - Eclipse Foundation에서 관리하는 오픈 소스 MQTT 브로커로, 경량이며 쉽게 설치·사용할 수 있다.
  2. RabbitMQ - AMQP(Advanced Message Queuing Protocol) 지원과 함께 MQTT 플러그인을 제공하는 오픈 소스 메시지 브로커이다.
  3. HiveMQ - 상업적으로 사용되는 MQTT 브로커로, 대규모 IoT 애플리케이션을 위해 설계되었다.
  4. EMQ X - 대규모 분산 환경을 위해 설계된 오픈 소스 MQTT 메시지 브로커로, 높은 처리량과 낮은 지연 시간을 자랑한다.

2. 스트리밍 - 메시지 배송의 구조와 주의점

대량으로 쏟아지는 메시지를 안정적으로 받아 쓰기 위해서, 분산 스토리지 앞단에는 메시지 브로커(Apache Kafka, Amazon Kinesis)가 설치된다. 다시 브로커와 스토리지 사이에는 컨슈머(consumer)가 소비하는 메시지의 양을 조절한다. 이렇게 메시지를 짧은 간격이라도 축적하여 차례로 데이터를 처리하는 것을 스트림 처리(stream processing)라고 한다. 또한 복수의 컨슈머(consumer)를 세팅하여 동일한 메시지를 여러 경로로 분기 처리도 가능하다.

이런 Pull 구조의 메시징 시스템은 메시지 배송에서 매우 중요한 위치를 가지고 있지만 그렇다고 만능은 아니다. 클라이언트의 수가 많아질수록 스트리밍형 메시지 배송의 성능신뢰성 모두 만족하기는 쉽지 않기 때문이다. 신뢰성을 보장하는 시스템은 다양한 방식으로 설계된다.

  1. at most once

    • 메시지는 최대 한 번만 전송된다. 하지만 도중에 유실될 가능성이 있다. 대부분 데이터의 결손을 막기 위해 재전송이 이루어지지만, 재전송이 이루어지는 시스템에서는 at most once를 보장하기 어렵다.
  2. exactly once

    • 메시지는 손실·중복 없이 정확히 한 번만 전송된다. 네트워크상에서 두 개의 노드가 있는 경우, 양쪽의 exactly once 통신을 보장하기 위해서는 둘 사이를 중계하는 코디네이터(coordinator)의 존재가 필수적이다. 하지만 코디네이터와의 통신에 장애가 발생할 수 있고, 응답이 너무 느리면 시간이 소요된다는 단점이 있다.
  3. at least once

    • 메시지는 적어도 한 번 확실히 전달되지만 여러 번 중복 전달되었을 가능성이 있다. 대부분의 메시지 배송 시스템은 at least once를 보장하지만, TCP/IP처럼 자동으로 중복 제거를 이루지는 못하고 사용자가 중복을 제거하여야 한다.

빅데이터 시스템에서는 신뢰성보다는 효율이 중시되며, 따라서 종단간 중간 경로에 at least once는 보장하면서 중복을 허용하고, 결론적으로 중복 제거는 나중에 값을 읽어들일 때 진행한다. 중복 제거는 아래와 같은 방법으로 이루어진다.

  1. offset을 이용한 중복 제거(offset 지점부터 다시 씀)
  2. UUID(Universally Unique IDentifier)에 의한 중복 제거
    • Cassandra, Elasticsearch는 특성상 고유 ID를 지정하게 되어 있어, 동일한 ID는 덮어쓰므로 중복 제거가 실현된다.

결론적으로, 빅데이터 시스템을 통해 신뢰성을 어느 정도는 확보할 수 있지만 신뢰성이 중시되는 경우에는 스트리밍형의 메시지 배송을 피하고 트랜잭션 처리를 지원하는 데이터베이스에 애플리케이션이 직접 기록하는 것이 제일 좋다.

3. 프로세스 시간과 이벤트 시간의 구별

스트리밍형의 메시지 배송에는 메시지 도착까지의 시간 지연 역시 고려해야 한다. 이벤트 시간프로세스 시간이 있으며, 실제 이벤트가 발생한 시간과 분산 스토리지에 넣은 서버상의 시간 사이에는 시간차가 있어 이를 감안하지 않은 전체 스캔(Full scan)은 효율이 떨어진다.

  • 이벤트 시간(event time) : 클라이언트에서 메시지가 생성된 시간
  • 프로세스 시간(process time) : 메시지를 서버가 처리하는 시간

이를 효율화하기 위해서는 다음과 같은 방법을 사용한다.

  1. Cassandra와 같은 시계열 인덱스(time-series index)에 대응하는 분산 데이터베이스를 이용한다. (장기간에는 적절하지 않음)

  2. 매일 한 번씩 새로 도착한 데이터를 이벤트 시간으로 정렬한 후 배치 처리를 통해 열 지향 스토리지로 변환한다. 열 지향 스토리지는 칼럼 단위 통계정보를 이용해 최적화가 이루어지며 최소한의 데이터만을 읽어들여 풀 스캔을 피한다. 이를 조건절 푸시다운(predicate pushdown)이라고 한다.

  3. 시간을 이용하여 분할된 테이블인 시계열 테이블(time-series table)에 시간 단위 파티션으로 저장한다. 더 나은 방법으로는, 데이터 수집 때는 프로세스 시간 기준으로 수집하고 추후 데이터 마트를 만들 때 이벤트 시간으로 정렬하여 유지한다.

4. NoSQL 데이터베이스의 특성

객체 스토리지는 아래와 같은 단점을 가지고 있다.

  • 객체 스토리지상의 파일은 교체하기 어렵다. 데이터베이스처럼 수시로 변경하는 용도에는 적합하지 않으며, 쓰기 빈도가 높은 데이터는 별도 RDB에 저장하고 스냅샷을 뜨거나 다른 분산 데이터베이스에 저장한다.
  • 객체 스토리지에 저장된 데이터는 집계를 위해 열 지향 스토리지를 만들지만, 데이터를 기록하고 곧바로 활용하기가 어렵다.

NoSQL은 위 상황에 최적화된 데이터 저장소이다. 간단하게 정리하면 다음과 같다.

  1. 분산 KVS(distributed Key-Value Store)

    • 모든 데이터를 키·값 쌍으로 저장하도록 설계된 데이터 저장소이다.
    • 모든 데이터에 고유 키를 지정하고, 부하 분산에 이용한다.
    • 마스터/슬레이브형이 있고 P2P형(Amazon DynamoDB)이 있다.
  2. 와이드 칼럼 스토어

    • 와이드 칼럼 스토어는 성능 향상이 목표이다.
    • 분산 KVS를 발전시켜 2개 이상의 임의의 키에 데이터를 저장할 수 있도록 한 것이다.
    • 대표적으로 GCP Bigtable, Apache HBase, Apache Cassandra가 있다.
    • 행 추가와 마찬가지로 열 추가도 자유롭게 할 수 있다.
  3. 도큐먼트 스토어

    • 도큐먼트 스토어는 데이터 처리의 유연성이 목표이다.
    • 스키마를 정하지 않고 데이터 처리가 가능하다.
    • 수평적 확장성을 지원하며 대량의 데이터를 다루는 대규모 애플리케이션에 특히 유용하다.
    • MongoDB, Couchbase, Amazon DynamoDB 등이 대표적인 도큐먼트 스토어 데이터베이스이다.

정리하며

이번 장의 내용을 정리하면 다음과 같다.

  • 스트리밍 데이터의 운반은 메시지 큐(message queue)메시지 브로커(message broker) 등의 중계 시스템을 통하며, 시스템의 특성에 맞게 구성한다.
  • 빅데이터 시스템은 신뢰성보다는 효율성을 중시하여, 종단간(End to End) 중간 경로에 at least once는 보장하면서 중복을 허용하여 저장한다. 추후 마트 구성 시에 중복을 제거한다.
  • 데이터 수집 때는 프로세스 시간 기준으로 수집하고 추후 데이터 마트를 만들 때 이벤트 시간으로 정렬하여 유지한다.

참고문헌