블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 


한시간에 만드는 대용량 로그 수집 시스템

조대협 (http://bcho.tistory.com)


정정 및 참고 내용

2017.1.24 몇가지 내용을 정정합니다.

https://cloud.google.com/logging/quota-policy 를 보면 스택드라이버 로깅에 쿼타 제한이 초당 500건/계정으로 잡혀있어서. 일반적인 경우는 최대 500 TPS의 성능을 낼 수 있습니다. 그 이상의 성능이 필요하면, 여러 계정을 사용해야 합니다 또는 구글에 별도의 쿼타 증설 요청을 해야 합니다.

하루에, 최대 2천5백만건의 로그를 하나의 프로젝트를 통해서 수집이 가능합니다.


또한 프리티어의 경우에는 한달에 로그를 5GB  까지 수집이 가능한데, 이게 넘으면 로그가 더이상 수집되지 않습니다. 그래서 아래 내용 처럼 빅쿼리로 Export를 해서 로그가 5GB 이상 스택드라이버에 저장되지 않도록 해야 합니다. (차기전에 데이타를 퍼나르는)

애플리케이션 로그 이외에도, VM 로그등도 이 5GB의 용량을 공유하기 때문에, VM 로그등도 차기전에 GCS로 퍼 나르거나 또는 구글 Support 티켓을 통하여 애플리케이션 로그 이외의 로그를 수집하지 않도록 별도 요청해야 합니다. (로그 저장 용량에 대해서 비용을 지불하면, 이런 제약은 없음)


백앤드 시스템에서 중요한 컴포넌트중의 하나가, 클라이언트로 부터 로그를 수집 및 분석하는 시스템이다.

오늘 설명할 내용은 500 TPS (Transaction Per Sec)가 넘는 대용량 로그 수집 및 분석 시스템을  managed 서비스를 이용하여, 쉽고 빠르게 구축할 수 있는 방법에 대해서 소개하고자한다.


일반적인 로그 수집 및 분석 시스템 아키텍쳐

일반적으로 클라이언트에서 로그를 수집하여 분석 및 리포팅 하는 시스템의 구조는 다음과 같다.


  • 앞단의  API 서버가 로그를 클라이언트로 부터 수집하고 데이타를 정재한다.

  • 로그 저장소가 순간적으로 많은 트래픽을 감당할 수 없는 경우가 많기 때문에, 중간에 Message Q를 넣어서, 들어오는 로그를 Message Q에 저장하여 완충을 한다.

  • 이 Message Q로 부터 로그를 Message Consumer가 순차적으로 읽어서 Log Storage에 저장한다.

  • 저장된 로그는 Reporting 툴을 이용하여 시각화 한다.


이런 구조 이외에도 API 서버에서 파일로 로그를 저장한 후,  Fluentd나, LogStash 등의 로그 수집기를 이용하는 방법등 다양한 아키텍쳐가 존재한다.


이런 시스템을 구축하기 위한 일반적인 솔루션들은 다음과 같다.


컴포넌트

솔루션


API 서버

node.js, ruby, php 등 일반적인 웹서버


Message Q

Rabbit MQ와 같은 일반적인 큐
Kafaka 와 같은 대량 큐

AWS SQS나 구글 Pub/Sub 같은 클라우드 큐


Message Consumer

Multi Thread(or Process) + Timer를 조합하여 메세지를 폴링 방식으로 읽어오는 애플리케이션 개발


Log Storage

Hadoop, HBase 와 같은 하둡 제품

Drill,Druid와 같은 SQL 기반 빅데이타 플랫폼

Elastic Search


Reporting

Zeppeline, Jupyter 와 같은 노트북류

Kibana



구조나 개념상으로는 그리 복잡한 시스템은 아니지만, 저러한 솔루션을 모두 배우고, 설치하고 운영하는데 시간이 들고, 각각의 컴포넌트를 구현해야하기 때문에 꽤나 시간이 걸리는 작업이다.


그러면 이러한 로그 수집 및 분석 작업을 클라우드 서비스를 이용하여 단순화 할 수 없을까?

스택 드라이버

스택 드라이버는 구글 클라우드의 모니터링, 로깅 및 애플리케이션 성능 분석등 모니터링 분야에서 다양한 기능을 제공하는 서비스 이다.

그중에서 스택드라이버 로깅은 구글 클라우드나 아마존 또는 기타 인프라에 대한 모니터링과, Apache, MySQL과 같은 써드 파티 미들웨어에 대한 로그 수집 및 모니터링을 지원하는데, 이 외에도, 사용자가 애플리케이션에서 로깅한 데이타를 수집하여 모니터링할 수 있다.



스택 드라이버와 빅쿼리를 이용한 로그 수집 분석 시스템 구현

스택 드라이버 로깅의 재미있는 기능중 하나는 로그 EXPORT 기능인데, 로그 데이타를 구글 클라우드 내의 다른 서비스로 로그 데이타를 내보낼 수 있다.


  • GCS (Google Cloud Storage)로 주기적으로 파일로 로그 데이타를 내보내거나

  • Pub/Sub이나 Big Query로 실시간으로 데이타를 내보낼 수 있다.


그렇다면 스택 드라이버를 통해서 빅쿼리에 로그 데이타를 직접 저장한다면 복잡한 Message Q나, Message Consumer 등의 구현도 불필요하고, 로그 저장도 복잡한 오픈 소스를 이용한 개발이나 운영도 필요 없이, 매니지드 서비스인 빅쿼리를 이용하여 간략하게 구현할 수 있다.

스택 드라이버 로깅을 이용한 로그 수집 시스템 구현


스택 드라이버 애플리케이셔 로깅 기능을 이용하여 클라이언트로 부터 로그를 수집하여 분석하는 시스템의 아키텍쳐를 그려 보면 다음과 같다.




API 서버를 이용하여 클라이언트로 부터 로그를 수집하고, API 서버는 스택 드라이버 로깅 서비스로 로그를 보낸다. 스택 드라이버 로깅은 Export 기능을 이용하여, 수집된 로그를 실시간으로 빅쿼리로 전송한다. 빅쿼리에 저장된 로그는 구글 데이타 스튜디오 (http://datastudio.google.com)이나 제플린, 파이썬 주피터 노트북과 같은 리포팅 도구에 의해서 시각화 리포팅이 된다.

API 서버쪽에서 스택 드라이버 로깅으로 로그를 보내는 부분을 살펴보자

아래는 파이썬 Flask 를 이용하여 로그를 스택 드라이버로 보내는 코드이다.


import uuid

from flask import Flask

from google.cloud import logging


app = Flask(__name__)

logging_client = logging.Client()

tlogger = logging_client.logger(‘my-flask-log’)

slogger = logging_client.logger('struct_log')

@app.route('/')

def text_log():

   logstring = "This is random log "+ str(uuid.uuid4())

   tlogger.log_text(logstring)

   return logstring


@app.route('/slog')

def struct_log():

   struct  = "This is struct log "+ str(uuid.uuid4())

   slogger.log_struct({

               'name':'myterry',

               'text':struct,

               'key' : 'mykey'})      

   return struct


if __name__ == '__main__':

   app.run('0.0.0.0',7001)

   

google.cloud 패키지에서 logging 모듈을 임포트한 다음에, 로깅 클라이언트로 부터

tlogger = logging_client.logger(‘my-flask-log’)

slogger = logging_client.logger('struct_log')

로 각각 “my-flask-log”와 “struct_log”라는 이름을 가지는 logger 둘을 생성한다.

(뒤에서 언급하겠지만, 이 로거 단위로, 로그를 필터링 하거나, 또는 이 로거 단위로 로그 메세지를 다른 시스템으로 export 할 수 있다.)


다음, 로그를 쓸 때는 이 logger를 이용하여 로그를 써주기만 하면 된다.

   tlogger.log_text(logstring)

는 텍스트로 된 한줄 로그를 쓰는 명령이고,

   slogger.log_struct({

               'name':'myterry',

               'text':struct,

               'key' : 'mykey'})  

는 JSON과 같이 구조화된 계층 구조를 로그로 쓰는 방식이다.

이렇게 개발된 로그 수집용 API 서버의 코드는 직접 VM을 만들어서 Flask 서버를 깔고 인스톨 해도 되지만  앱앤진을 사용하면 코드만 배포하면, Flask 서버의 관리, 배포 및 롤백, 그리고 오토 스케일링등 모든 관리를 자동으로 해준다. 앱앤진을 이용한 코드 배포 및 관리에 대한 부분은 다음 문서 http://bcho.tistory.com/1125 를 참고 하기 바란다.

스택 드라이버에서 로그 확인

코드가 배포되고, 실제로 로그를 기록하기 시작했다면 스택 드라이버에 로그가 제대로 전달 및 저장되었는지 확인해보자. 구글 클라우드 콘솔에서 스택 드라이버 로깅으로 이동한 다음 아래 그림과 같이 리소스를 “Global” 을 선택한 후, 앞에 애플리케이션에서 남긴 “my-flask-log”와 “struct-log” 만을 선택해서 살펴보자





다음과 같이 로그가 출력되는 것을 확인할 수 있으며, struct_log의 예를 보면 로그의 내용은 time_stamp  와 프로젝트 정보와 같은 부가 정보와 함께, 애플리케이션에서 남긴 로그는 “jsonPayload” 앨리먼트 아래에 저장된것을 확인할 수 있다.



빅쿼리로 Export 하기

스택 드라이버로 로그가 전달되는 것을 확인했으면, 이 로그를 빅쿼리에 저장해보자. Export 기능을 이용해서 가능한다. 아래와 같이 스택 드라이버 로깅 화면에서 상단의 “CREATE EXPORT”  버튼을 누른다.

다음 리소스 (Global)과 로그 (struct_log)를 선택한 다음에,



Sink Name에 Export 이름을 적고 Sink Service는 BigQuery를 선택한다. 다음으로 Sink Destination에는 이 로그를 저장할 Big Query의 DataSet 이름을 넣는다.

마지막으로 Create Sink를 누르면, 이 로그는 이제부터 실시간으로 BigQuery의 structlog라는 데이타셋에 저장이 되면 테이블명은 아래 그림과 같이 strcut_log_YYYYMMDD와 같은 형태의 테이블로 생성이 된다.




테이블 프리뷰 기능을 이용하여 데이타가 제대로 들어갔는지 확인해보자. 아래와 같이 위의 코드에서 저장한 name,key,text는 테이블에서 jsonPayload.name, jsonPayload.key, jsonPayload.text 라는 필드로 각각 저장이 되게 된다.



빅쿼리는 실시간으로 데이타를 저장할때는 초당 100,000건까지 지원이 가능하기 때문에 이 시스템은 100,000TPS 까지 지원이 가능하고, 만약에 그 이상의 성능이 필요할때는 로그 테이블을 나누면(Sharding) 그 테이블 수 * 100,000 TPS까지 성능을 올릴 수 있다. 즉, 일별 테이블을 10개로 Sharding 하면, 초당 최대 1,000,000 TPS를 받는 로그 서비스를 만들 수 있으며, 이 테이블 Sharding은 빅쿼리 테이블 템플릿을 사용하면 쉽게 설정이 가능하다. (정정 빅쿼리는 100K TPS를 지원하나, 스택 드라이버가 500 TPS로 성능을 제한하고 있음)


이렇게 저장된 로그는 빅쿼리를 지원하는 각종 리포팅 툴을 이용하여 시각화가 가능하다.

시각화 도구는

을 참고하기 바란다.


이렇게 간단하게, 코드 몇줄과 설정 몇 가지로 100,000 500 TPS 를 지원하는 로그 서버를 만들어 보았다.

스택 드라이버를 이용한 로그 분석 수집 시스템의 확장

이 외에도 스택 드라이버는 빅쿼리뿐 아니라 다른 시스템으로의 연동과 매트릭에 대한 모니터링 기능을 가지고 있어서 다양한 확장이 가능한데, 몇가지 흥미로운 기능에 대해서 살펴보도록 하자.


실시간 스트리밍 분석 및 이벤트 핸들링

스택 드라이버 로깅의 Export 기능은, 하나의 로그를 여러 연동 시스템으로 Export를 할 수 있다. 앞에서는 빅쿼리로 로그를 Export 하였지만, 같은 Log를 Dataflow에 Export 하였을 경우, 로그 데이타를 실시간 스트림으로 받아서, 실시간 스트리밍 분석이 가능하다.


구글 데이타 플로우에 대한 설명은 아래 링크를 참고하기 바란다.


또는 실시간 스트리밍이 아니라, 로그 메세지 하나하나를 받아서 이벤트로 처리하고자 할 경우, Pub/Sub 큐에 넣은 후에, 그 뒤에 GAE또는 Cloud function (https://cloud.google.com/functions/) 에서 메세지를 받는 구조로 구현이 가능하다.


로그 모니터링

스택 드라이버 로깅은 단순히 로그를 수집할 뿐만 아니라 훨씬 더 많은 기능을 제공한다.

앞에서 스택 드라이버 로깅을 이용한 로그 수집 시스템을 만드는 방법을 알아보았지만, 부가적인 몇가지 기능이 같이 제공되는데 다음과 같다.

필터를 이용한 특정 로그 핸들링

logger를 통해서 수집된 로그에는 필터를 걸어서 특정 로그만 모니터링할 수 있다.

예를 들어서 text 문자열에 “error” 가 들어간 로그나, latency가 1초이상인 로그와 같이 특정 로그만을 볼 수 있다.

다음은 jsonPayload.text 로그 문자열에 “-a”로 시작하는 문자열이 있는 로그만 출력하도록 하는 것이다.



이 기능을 사용하면, 로그 메세지에서 특정 로그만 쉽게 검색하거나, 특정 에러 또는 특정 사용자의 에러, 특정 ErrorID 등으로 손쉽게 검색이 가능해서 로그 추적이 용이해진다.

매트릭 모니터링

다음은 메트릭이라는 기능인데, 로그를 가지고 모니터링 지표를 만들 수 있다.

예를 들어 하루 발생한 에러의 수 라던지, 평균 응답 시간등의 지표를 정의할 수 있다.

이렇게 정의된 지표는 대쉬보드에서 모니터링이 가능하고 또는 이러한 지표를 이용하여 이벤트로 사용할 수 있다. 응답시간이 얼마 이상 떨어지면 오토 스케일링을 하게 한다던가 또는 이메일로 관리자에게 ALERT을 보낸다던가의 기능 정의가 가능하다.


매트릭 생성

지표 정의는 로그 화면에서 필터에 로그 검색 조건을 넣은 채로, CREATE METRIC 버튼을 누르면 사용자가 지표를 매트릭으로 정의할 수 있다.



대쉬 보드 생성


이렇게 정의된 매트릭은 스택 드라이버 대쉬 보드 화면에서 불러다가 그래프로 시각화가 가능한데, 다음 그림은 struct_log의 전체 수와를 나타내는 매트릭과, struct_log에서 log text에 “-a”를 포함하는 로그의 수를 나타내는 메트릭을 정의하여 차트로 그리는 설정이다.



위에 의해서 생성된 차트를 보면 다음과 같이 전체 로그 수 대비 “-a”  문자열이 들어간 로그의 수를 볼 수 있다.


지금까지 스택드라이버 로깅과 빅쿼리를 이용하여 간단하게 대용량 로그 수집 서버를 만드는 방법을 살펴보았다. 두개의 제품을 이용해서 로그 수집 시스템을 구현하는 방법도 중요하지만, 이제는 개발의 방향이 이러한 대용량 시스템을 구현하는데, 클라우드 서비스를 이용하면 매우 짧은 시간내에 개발이 가능하고 저비용으로 운영이 가능하다. 요즘 개발의 트랜드를 보면 이렇게 클라우드 서비스를 이용하여 개발과 운영 노력을 최소화하고 빠른 개발 스피드로 개발을 하면서, 실제로 비지니스에 필요한 기능 개발 및 특히 데이타 분석 쪽에 많이 집중을 하는 모습이 보인다.


단순히 로그 수집 시스템의 하나의 레퍼런스 아키텍쳐에 대한 이해 관점 보다는 전체적인 개발 트렌드의 변화 측면에서 한번 더 생각할 수 있는 계기가 되면 좋겠다.


빅쿼리-#3 데이타 구조와 데이타 공유 권한관리


조대협 (http://bcho.tistory.com)


빅쿼리에 대한 개념 및 내부 구조에 대한 이해가 끝났으면, 빅쿼리의 데이타 구조와, 데이타에 대한 권한 관리에 대해서 알아보도록 한다.

데이타 구조

빅쿼리의 데이타 구조는 다음과 같은 논리 구조를 갖는다. 일반적인 RDBMS와 크게 다르지 않다.





데이타 구조

프로젝트 (Project)

먼저 프로젝트라는 개념을 가지고 있다. 하나의 프로젝트에는 여러개의 데이타셋이 들어갈 수 있다.

데이타셋 (Dataset)

데이타셋은 MySQL의 DB와 같은 개념으로, 여러개의 테이블을 가지고 있는 테이블의 집합이다. 이 단위로 다른 사용자와 데이타를 공유할 수 있다.

테이블 (Table)

데이타를 저장하고 있는 테이블이다.

잡 (Job)

쿼리나, 데이타 로딩, 삭제와 같이 데이타에 대해서 어떤 명령을 내렸을때, 그 명령을 잡(Job)이라고 하며, 각 Job들은 누가 언제 어떤 내용을 수행하였는지, 향후 감사를 목적으로 모두 로깅 된다.

데이타 타입

테이블에 저장될 수 있는 데이타 구조는 다음과 같다.

  • STRING : UTF-8인코딩. 최대 2MB

  • INTEGER : 64 bit

  • FLOAT :  Double precision

  • BOOLEAN

  • RECORD : Collection of one or more field

  • TIMESTAMP


특이한 것이 RECORD 라는 데이타 타입인데, 레코드는 JSON과 같이 여러개의 데이타를 가지는 데이타형을 이야기한다.


아래 그림은 웹UI에서 ID와 NAME이라는 두개의 컬럼을 가지고 있는 테이블을 생성하는 화면이다.

Name은 앞서 설명한 RECORD  타입으로 정의했고, Name 필드 안에는 Last_name과, First_name이라는 STRING형 필드를 갖는다.



이렇게 생성된 테이블의 구조는 다음과 같이 된다.


RECORD 형 데이타 타입 안에는 앞서 정의된 STRING,INTEGER 등의 데이타 타입으로 컬럼 정의가 가능하며, RECORD 형 데이타 타입이 또 그 안에 들어갈 수 있다.  (JSON 데이타형과 매우 유사하다고 보면 된다).


REPEATED FIELD

테이블내의 각 컬럼의 값들은 NULL (값이 없거나), 일반적인 테이블 처럼 1개의 값을 가질 수 도 있지만, 컬럼을 정의할때, REPEATABLE 이라고 정의하면 하나의 필드에도 여러개의 값을 가질 수 있다. (JSON의 배열 처럼)




위는 웹 UI에서, ID와 Basket이라는 두개의 STRING 필드를 가지고 있는 테이블을 정의하는 화면이고 그중, Basket을 REPEATED 필드로 정의하였다.

이렇게 정의된 테이블의 모양은 다음과 같다.



Terry.cho 데이타 처럼 Basket 하나의 컬럼에 여러개의 데이타를 가지고 있는 것을 볼 수 있다.

권한 관리 및 공유

빅쿼리는 여러 사람이 각자의 계정을 가지고 사용을 할 수 있으며, 각 사용자별로 특정 데이타셋에 대한 수정,조회,삭제 권한을 부여할 수 있다.

권한 적용 대상

권한을 적용하여 접근을 통제할 수 있는 대상은 프로젝트와, 데이타셋이다. (테이블 단위로는 권한 적용이 불가)


권한 부여 대상

  • 사용자
    개인 사용자에게 데이타에 대한 권한을 지정할 수 있다.

  • 구글 그룹스 기반의 사용자 집합
    다수의 사용자가 속해 있는 구글 그룹스 (https://groups.google.com/) 사용자들에게 권한을 지정할 수 있다.

  • 특정 역할(ROLE)을 가지고 있는 사용자
    사용자중에서 특정한 역할 (관리자, 부서등)을 가지고 있는 사용자들에게 권한을 지정할 수 있다.


권한 종류

데이타셋 권한

  • READER : 데이타셋에 대한 데이타 조회 가능

  • WRITER : 데이타셋 내의 테이블에 대한 생성, 데이타 조회 및 추가 가능

  • OWNER:  데이타셋 업데아트 및 삭제 가능

프로젝트 권한

  • Viewer : JOB 수행과 수행중인 JOB 모니터링 가능. 데이타셋에 대한  READER 권한

  • Editor : 데이타셋 생성 가능 + 데이타셋에 대한 WRITER 권한

  • Owner :  데이타셋에 대한 모든 JOB 수행 가능. 데이타셋 삭제 가능


데이타셋 권한

데이타 공유 하기

데이타셋 공유

빅쿼리 웹UI에서 다른 사람과 공유하고자 하는 데이타셋을 선택한 후에, “Share dataset” 이라는 메뉴를 선택하면 아래와 같이 데이타셋 공유 메뉴가 출력 된다.



이 메뉴에서 공유 적용 대상 (특정인, 이메일 그룹이나 특정 역할)을 선택하고 공유 권한 (View, Edit, Owner) 권한을 부여하면 공유를 부여 받은 대상이 이 데이타 셋에 접근할 수 있다.


데이타셋의 소유자가 데이타셋을 공유했다고, 공유 받는 쪽에서 자동으로 데이타가 보이는 것은 아니며, 데이타를 공유 받는 쪽에서, 프로젝트에서 Switch Project 메뉴를 선택한 후 Display Project메뉴를 선택하면


Add project 창이 나온다. 이때 앞에서 공유된 프로젝트 명을 입력한다. (공유된 프로젝트명을 알고 있어야 한다.)

그러면 공유된 데이타 셋이 속한 프로젝트와 공유되니 데이타셋이 좌측에 표시되고 접근이 가능하게 된다.




그림. github archive 프로젝트와 그아래 github,day 데이타셋이 공유되어 추가된 화면



프로젝트 공유

데이타셋 단위뿐 아니라 조금 더 큰 범주에서 프로젝트 자체를 공유할 수 있다.

프로젝트에 대한 권한 관리는 구글 클라우드 메뉴에서 IAM & Admin 메뉴로 들어가서


 IAM 메뉴에서 Add members를 선택하면, 아래 그림과 같이 사용자 이름을 입력할 수 있는 텍스트 박스가 뜨고, 우측에 Select Role 리스트 박스가 나온다. 여기서 Projects 메뉴를 선택하면 하부 메뉴로, Owner, Editor, Viewer 등의 권한을 부여할 수 있다.




빅쿼리의 데이타 구조, 데이타 타입 그리고 권한 접근 구조에 대해서 알아보았다.

다음에는 실제로 프로젝트와 데이타셋을 생성하고, 테이블을 생성한 후 데이타를 로딩해보도록 하겠다.


빅쿼리 #2-아키텍쳐


조대협 (http://bcho.tistory.com)


이번글에서는 앞에서 소개한 구글의 대용량 데이타 저장/분석 시스템인 빅쿼리의 내부 아키텍쳐에 대해서 알아보도록 한다.

컬럼 기반 저장소

다음과 같은 테이블이 있다고 하자




전통적인 데이타 베이스는 파일에 물리적으로 데이타를 저장할때 개념 적으로 다음과 같은 방식으로 저장한다.


FILE 1 : “001;Cho;Terry;Seoul;30,002;Lee;Simon;Suwon;40,003;Kim;Carl;Busan;22”


그래서 하나의 레코드를 가지고 오면 그 레코드에 해당하는 모든 값을 가지고 올 수 있다.

반면 컬럼 기반 저장소의 경우에는 각 컬럼을 다음과 같이 다른 파일에 나눠서 저장한다.


FILE 1: 001:Cho,002:Lee,003:Kim

FILE 2: 001:Terry,002:Simon,003:Carl

FILE 3: 001:Seoul;002:Suwon:003:Busan

:


이렇게 컬럼 단위로 저장을 하게 되면 장점은 Last Name 컬럼의 내용만 읽고 싶을때 로우 단위로 저장한 시스템의 경우, 모든 데이타를 다 스캔해야 하는데, 컬럼 단위로 저장한 시스템은 Last Name을 저장한 파일 하나만 스캔하면 되고, Last Name 이외의 다른 컬럼의 데이타는 읽어드리지 않아도 되기 때문에 데이타 효율성이 높다.


그래서 특정 컬럼만 읽어서 개수를 세거나 통계를 내는 분석용 데이타 베이스(OLAP)  작업등에 유리하다.

Columnar databases boost performance by reducing the amount of data that needs to be read from disk, both by efficiently compressing the similar columnar data and by reading only the data necessary to answer the query.

In practice, columnar databases are well-suited for OLAP-like workloads (e.g., data warehouses) which typically involve highly complex queries over all data (possibly petabytes). However, some work must be done to write data into a columnar database. Transactions (INSERTs) must be separated into columns and compressed as they are stored, making it less suited for OLTP workloads. Row-oriented databases are well-suited for OLTP-like workloads which are more heavily loaded with interactive transactions.”

출처 : https://en.wikipedia.org/wiki/Column-oriented_DBMS

실제로 빅쿼리도 하나의 파일에 하나의 컬럼 데이타만 저장하도록 되어 있다.

빅쿼리는 앞의 글에서도 설명하였듯이 데이타의 안정성을 위해서 3개의 데이타 센터에 나눠서 데이타를 저장하는데, 각 컬럼을 저장하는 파일이 총 3개의 복제본으로 그림과 같이 각각 다른 데이타 센터에 나줘서 저장이 된다.


트리 구조의 데이타 처리 구조

실제로 빅쿼리의 시스템 구조는 다음과 같이 되어있다.



출처 https://codelabs.developers.google.com/codelabs/cp100-big-query/#3


GFS (Google File System)의 후속 파일 시스템인 분산 스토리지 Colossus가 맨 아래에서 저장소를 제공하고, Jupiter 라는 TB 급의 네트워크 망을 통해서, 컴퓨팅 노드와 통신을 한다.

그리고 연산을 담당하는 컴퓨팅 계층은 Leaf , Mixer 1, Mixer 0 계층으로 되어 있다.

이 컴퓨팅 계층은 디스크 없이 Colossus에서 읽은 데이타를 처리해서 각각 위의 계층으로 올리는 역할을한다.


다음 SQL이 어떻게 연산이 수행되는지를 살펴보면 아키텍쳐를 이해할 수 있다.




natality라는 테이블에서 1980~1990년대에 태어난 아이들의 수를 주(state)별로 그룹핑해서 내림차순으로 정렬한 후 상위 10개의 데이타만 출력해주는 쿼리이다.


이 쿼리를 수행하면 빅쿼리는 내부적으로 다음과 같은 연산을 수행한다.



  • STORAGE : 디스크에서 STATE,YEAR 컬럼만을 읽어드린다.

  • LEAF : 다음 각각의  LEAF 노드에서, 읽어드린 데이타를 가지고 1980~1990년대 데이타를 주 단위로 태어난 아이들의 수를 카운팅 한다.

  • MIXER 1:에서 LEAF에서 계산해온 주(STATE) 별 아이들의 수를 합친다.

  • MIXER 0:에서는 MIXER 1에서 올라온 모든 값을 합치면서 소팅을 한다. (머지 소트를 생각하면 된다.). 소팅이 끝난 후에, 맨 위의 10개의 레코드만을 리턴한다.


조인이나 그룹핑의 경우 조금 더 복잡한 연산이 실행되기는 하지만 큰 흐름은 유사하다.

다른 구조적인 특징

빅쿼리가 대용량과 성능을 지원하기는 하지만 일반적인 데이타 베이스와 다소 다른 특성을 가지고 있다.

NO-KEY,NO-INDEX (FULL SCAN ONLY)

빅쿼리에는 키나 인덱스의 개념이 없다. 무조건 풀스캔이다. (스캔의 범위를 조정할 수 있는 기법이 있는데 이는 나중에 설명하도록 한다.)

NO UPDATE,DELETE ROW

빅쿼리는 성능을 위해서 테이블에 데이타를 추가 (APPEND)하는 것만을 지원한다. 한번 입력된 데이타는 변경되거나 삭제될 수 없으며, 데이타가 잘못 입력되었을 경우에는 테이블을 지우고 다시 생성해야 한다. (이 문제를 해결하는 디자인 패턴에 대해서는 나중에 설명한다.)

EVENTUAL CONSISTENCY

데이타를 3개의 데이타 센터에 걸쳐서 복제하기 때문에, 데이타를 입력한 후 바로 조회하면 데이타가 조회가 되지 않을 수 있다. 이는 데이타를 복제하는데 소요되기 때문인데, 보통 바로 반영되거나 상황에 따라서 최대 수분이 걸릴 수 있다.


다음 글에서는 빅쿼리의 데이타 모델과 인터페이스에 대해서 알아보도록 한다.


참고 자료





구글 빅데이타 플랫폼 빅쿼리 소개


조대협 (http://bcho.tistory.com)


구글의 클라우드 관련 기술중 무엇이 좋은게 있을까 살펴 보면서 기술을 하나하나씩 보다 보니, 구글 클라우드의 특징은 여러가지가 있겠지만, 데이타 회사 답게 빅데이타 및 머신 러닝 플랫폼이 상당히 강하다.


그중에서 빅데이타 플랫폼의 중심에 BIG QUERY라는 빅데이타 플랫폼이 있어서, 몇 회에 걸쳐서 빅쿼리에 대해서 소개해보고자 한다.

구글 빅데이타 분석의 역사

구글은 빅데이타를 다루면서, 그 근간이 되는 기술들의 논문들을 공개했다. 하둡 파일 시스템의 시초가 되는 GFS나, 하둡의 시초인 MapReduce 논문, 그리고 Hive를 통해 오픈소스화가 된 Big Table등의 논문들이 있다. 구글의 빅쿼리는 Dremel 이라는 논문을 근간으로 한다.

빅쿼리랑 무엇인가?

빅쿼리는 페타 바이트급의 데이타 저장 및 분석용 클라우드 서비스이다.

요즘은 페타바이트급의 data warehouse로 부르는데, 쉽게 말해서 페타바이트급의 데이타를 저장해놓고, 쿼리를 통해서 조회나 통계 작업등을 할 수 있는 DB(라고 보기에는 약간 애매하지만)이다.

빅쿼리의 특징

대략적인 특징을 살펴보면 다음과 같다.

클라우드 서비스로 설치/운영이 필요 없음 (NoOps)

어디에 설치해서 사용하는 서비스가 아니라 구글 클라우드 서비스를 통해서 제공되는 빅데이타 저장 분석 서비스이다. 클릭 몇번으로 서비스 사용이 가능하고, 별도의 설정이나 운영이 필요 없다.

SQL 언어 사용

기존의 RDBMS에서 사용되는 SQL언어를 그대로 사용하기 때문에, 사용이 매우 쉽다.

클라우드 스케일의 인프라를 통한 대용량 지원과 빠른 성능

빅쿼리의 성능이나 스케일을 보려면 다음 예제를 보는게 좋다.

https://cloud.google.com/blog/big-data/2016/01/anatomy-of-a-bigquery-query


위키피디아에서 100 billion record (1000억개)의 레코드를 스캐닝해서 regular expression으로 “G.*o.*o.*g”) 문자열을 찾아내서 그 문서의 뷰수를 카운트 하는 예제이다.

대략 4TB 용량의 데이타가 핸들링 되고, 약 30초가 소요된다.

30초 동안, 약 3,300개의 CPU와, 330개의 하드 디스크, 330 Gigabit의 네트웍이 사용된다.

(자료 : https://cloud.google.com/blog/big-data/2016/01/bigquery-under-the-hood)

이 쿼리를 수행하는데 소요되는 비용은 딱 $20가 소요된다.

일반적인 인프라에서 빅데이타 연산을 하는데, 3300개의 CPU를 동시에 사용하기란 쉽지 않은 일이고, 이런 대용량 연산을 20$에 할 수 있는 것은 대용량 인프라를 공유하는 클라우드 서비스이기 때문에 가능하다.

데이타 복제를 통한 안정성

데이타는 3개의 복제본이 서로 다른 3개의 데이타 센터에 분산되어 저장되기 때문에 데이타에 대한 유실 위험이 적다.

배치와 스트리밍 모두 지원

한꺼번에 데이타를 로딩하는 배치 이외에도 REST API등을 통해서 실시간으로 데이타를 입력할 수 있는 스트리밍 기능을 제공하며, 스트리밍시에는 초당 100,000개의 행(row)의 데이타를 입력할 수 있다.

비용 정책

비용 정책 역시 클라우드 서비스 답게, DB 인스턴스와 같은 과금 방식이 아니라서 큰 데이타를 핸들링 하기 위해서 큰 인스턴스를 쓰고 사용하지 않는 동안에도 과금이 되는 정책이 아니라,

딱  저장되는 데이타 사이즈와, 쿼리시에 발생하는 트렌젝션 비용만큼만 과금이 된다.  데이타 저장 요금은 GB당 0.02$이고, 90일이 지나서 사용하지 않는 데이타는 자동으로 0.01$로 가격이 떨어진다.

클라우드 서비스에서 가격이 싸다는 일반적인 오브젝트 스토리지 (Google Cloud Storage : GB당 0.026$)보다 싸다. 트렌젝션 비용은 쿼리 수행시 스캔되는 데이타를 기준으로 TB당 $5 이다.  (월  1TB는 무료)
(나중에 자세하게 설명하겠지만, 스캔되는 컬럼당 비용이 나오기 때문에 사실상 비용을 계산해보면 그리 높지 않다)

가격 정책 : https://cloud.google.com/bigquery/pricing


빅쿼리가 기존의 빅데이타 플랫폼과 다른점은?

그렇다면 빅쿼리가 기존의 빅데이타 분석 플랫폼인 Hadoop, Spark등과의 차이가 무엇일까? 앞의 장점을 기반으로 그 차이점을 정리하자면 크게 다음과 같은 3가지를 들 수 있다.

쉽다.

보통 Hadoop이나 Spark등을 사용하게 되면, Map&Reduce(이하 MR) 로직을 사용하거나 SparkSQL을 사용하더라도 일정 수준 이상의 전문성이 필요하다. 또한 MR 로직의 경우 전문성이 있는 개발자가 분석 로직을 개발해야 하기 때문에 시간이 상대적으로 많이 소요되지만 빅쿼리는 로그인 후 SQL만 수행하면 되기 때문에, 상대적으로 빅데이타 분석이 쉽다.

운영이 필요 없다

Hadoop이나 Spark과 같은 빅데이타 솔루션의 경우에는 인스톨과 설정 그리고 클러스터의 유지 보수가 보통 일이 아니다. 그래서 별도의 운영 조직이 필요하고 여기에 많은 리소스가 소요되지만, 빅쿼리는 클라우드 서비스 이기 때문에, 별도의 운영등에 신경을 쓸 필요가 없이 개발과 분석에만 집중하면 된다.  

인프라에 대한 투자없이 막강한 컴퓨팅 자원을 활용

앞의 예에서 본것과 같이, 빅쿼리를 이용하면 수천개의 CPU와 수백/수천개의 컴퓨팅 자원을 사용할 수 있다. 물론 기존 빅데이타 플랫폼도 클라우드 환경에 올리면 수천개의 CPU를 사용하는 것이 가능은 하지만, 그 설정 작업과 비용적인 측면에서 차이가 크다.

빅쿼리 맛보기

그러면 직접 빅쿼리를 사용해보자. 빅쿼리 버전 HelloWorld라고 생각하면 된다.

가입 하기

http://cloud.google.com 으로 들어가서 구글 클라우드 서비스에 가입을 한후에,  로그인을 해서 아래 그림 처럼 결재 메뉴에서 빌링 정보를 입력한다 (신용 카드 정보 입력)



계정이 생성되면 자동으로 $300 의 무료 사용권이 생성되고, 이 금액은 60일동안 사용할 수 있다. (60일이 지나면 자동으로 소멸된다. ).

신용 카드 정보를 넣었더라도, 사용자가 직접 과금이 되는 플랜으로 업그레이드를 하지 않는 이상 과금이 되지 않으니 이 부분은 걱정하지 말기 바란다.

프로젝트 생성

구글 클라우드는 VM이나 각종 자원들을 프로젝트라는 개념으로 묶어서 사용한다. 처음 계정을 생성했으면 프로젝트가 없기 때문에 프로젝트를 생성하자.

아래 그림과 같이 상단 우측 메뉴에 프로젝트 생성 메뉴가 있다.


프로젝트 생성을 선택한 후 아래와 같이 프로젝트 이름을 입력하면 프로젝트가 생성된다.


빅쿼리 콘솔로 이동하기

프로젝트가 생성되었으면 메뉴에서 아래 그림과 같이 BigQuery 메뉴를 선택하게 되면 빅쿼리 웹 콘솔로 이동이 된다.




빅쿼리 메뉴로 들어가면 다음과 같은 작업 창이 나온다.




좌측은 프로젝트와 프로젝트에 속한 데이타셋과 테이블 리스트가 나온다.

나중에 데이타 모델을 다시 설명하겠지만, 데이타 셋 (dataset)은 RDBMS의 db와 같은 개념으로 테이블의 집합이라고 보면 되고, 그 안에 개별 테이블들이 들어가 있다.

우측 상단 쿼리 입력창에는 SQL을 입력해서 쿼리를 실행하고, 우측 아래에는 쿼리 결과를 볼 수 있다.

쿼리 실행

그러면 실제로 간단한 쿼리를 수행해보자

빅쿼리에서는 테스트를 위해서 몇가지 데이타 셋을 공개로 해놓았는데, bigquery-samples라는 데이타 셋에서 1000억개의 레코드를 가지고 있는  wikipedia_benchmark.Wiki100B 테이블에서, 위키 페이지 제목이 “Seoul”또는 “seoul”인 페이지의 제목과 뷰수를 쿼리를 해본다.


다음과 같이 쿼리를 입력하고


select title,sum(views) as views

from [bigquery-samples:wikipedia_benchmark.Wiki100B]

where regexp_match(title,'[Ss]eoul')

group by title

order by views desc;


쿼리 입력창 하단에 체크 마크를 누르면 다음과 같은 화면이 출력된다.


쿼리를 수행하기 전에, 쿼리가 제대로 되었는지 확인을 해주고, 위와 같이

Valid: This query will process 3.64 TB when run.”

3.64 TB를 스캐닝 할것임을 알려준다. (이를 통해서 쿼리 수행 비용을 예측해볼 수 있다.)


“Run Query” 버튼을 눌러서 쿼리를 수행하면 다음과 같은 결과를 얻을 수 있다.


RUN QUERY 버튼 가장 우측에 총 3.64TB를 처리했고, 총 수행 시간은 38.9초가 걸렸음을 확인할 수 있다.

그리고, 아래 쿼리 결과가 나온다.

Seoul 로 된 페이지가 11258720회 조회되었고, Seoul_National_University가 다음으로 894040회, FC_Seoul이 802570회 조회 된것을 확인할 수 있다.


지금까지 간략하게나마 빅쿼리에 대한 소개와 주요 특징 그리고 간단한 사용법을 소개했다.

다음 글에서는 빅쿼리의 내부 아키텍쳐에 대해서 설명하도록 한다.