클라우드 환경을 손쉽게 구축하기위한 DC/OS 알아보기

현대 웹개발은 모노리틱(Monolithic) 방식을 넘어 마이크로서비스(Microservice)를 지향하는 방식으로 넘어가고 있습니다.

 단일 웹 어플리케이션이 아닌 여러가지의 서비스가 조합된, 어떻게 보면 더 복잡한 아키텍처일 수 있지만 이러한 문제점을 단순화하여 해결하려는 노력들이 있습니다.

 다수의 장비 및 다수의 솔루션들이 복잡하고 다양한 커뮤니케이션에 의해 서비스되는 웹서비스의 아키텍처는 기존의 시스템 아키텍처로 커버하기는 어려운 점이 많은 상황입니다. 일반적인 서비스에서 사용되는 모노리틱 어플리케이션의 특징을 우선 알아보도록 하겠습니다.

 

모노리틱 어플리케이션 특징

 - 하나의 ear 또는 war안에 모든 내용이 들어가 있음.

 - 재사용 가능한 부분은 sharing.jar와 같이 jar영역에 대해서만 재사용 가능

 - 일년에 한두번 대규모 push 를 통한 업데이트 (못하는 경우도 많음)

 - 500k 라인 이상의 코드

 - heavyweight infrastructure

 - 수없이 많은 테스트 케이스

 - 대규모의 팀 규모

 - 많은 버그 목록

 

이러한 모노리틱 어플리케이션을 H/W 장비마다 서비스를 구성하고 여러 사용자를 대응하기 위하여, 다수의 장비를 구성해야 하는 경우 보통 3~4대 정도까지는 힘들겠지만 어느정도 서버 설정 및 구성을 하겠지만, 그 이상의 서버를 설정하는 것은 매우 노동집약적 힘든 중노동이 될 수 있습니다. 또한 이러한 환경의 가용성(HA)을 높이기 위하여 수많은 안정성 테스트 및 소스 개발.배포 등도 매우 복잡해 질 수 있습니다.

 

[ 빅데이터 처리를 위한 장비 아키텍처 발전사]


이러한 문제점을 해결하며, Amazon이나 Google Cloud와 같은 인프라를 이용하거나,  관리 용이성을 위하여 Docker와 같은 container 기반의 인프라를 통한 Modern Web Application 을 개발하는 시대가 다가오고 있습니다.

 수많은 서버장비에 자신이 원하는 서비스 및 기능을 손쉽게 설치하고, 관리하고, 특정 서버가 죽으면, 자동으로 해당 서비스를 다른 서버로 이동해주고, 마치 스마트폰의 앱처럼 기업용 솔루션을 클라우드 환경처럼 손쉽게 관리할 수 있는 솔루션이 있다면 얼마나 편리할까요?

 

이러한 편리한 기능을 제공하며 새로운 마이크로서비스 아키텍처로 이동하기 위한 인프라를 제공하는 Container 관리 솔루션들이 이미 몇가지 있습니다.

 그중에서 Apache 오픈소스 진영에서 개발되어 가장 많은 사용자 지원을 받고 있는 Mesos DCOS에 대해서 설명하도록 하겠습니다.



STATIC PARTITIONING to ELASTIC SHARING

 DC/OS는 Data Center OS 즉 Data Center와 같이 대규모 서버 환경을 하나의 OS처럼 관리하고 하는 목적으로 개발되었습니다. 여러 서버 환경을 하나의 자원처럼 관리하기 위해서는 기존의 정적 파티션 개념에 의한 고정된 자원 분배개념이 아닌 유연한 공유(Elastic sharing)에 의한 각 서버 자원의 자유로 효율적인 사용이 주요 이슈이며 이를 OS처럼 손쉽게 처리하기 위한 목적이 DCOS의 목적입니다.

일반적으로 대부분 기업 인프라는 정해진 하드웨어 장비에 정해진 솔루션만 설치하여 이용하는 방법을 많이 사용했습니다.

정적파티션 방법은 다음의 큰 단점을 가지고 있습니다.

  • 장애대응

  • 자원낭비

즉 하나의 하드웨어나 솔루션에 문제가 생기면 전체시스템의 문제로 발생되고 시스템 장원이 효과적으로 이용하기 어렵기 때문에 자원낭비가 발생합니다.

이러한 문제점을 해결하기 위하여 동적 공유를 통해 자원을 자동적으로 분배하는 기술이 필요합니다.

즉 여러 물리적 하드웨어 장비를 커널 레벨에서 하나의 자원처럼 관리하는 클러스터링 관리자가 필요했고 이러한 역할을 하는 것이 Apache Mesos 로 개발 및 발전되고 있습니다.


[아키텍처별 자원 파티셔닝 구조도] 



Apache Mesos 특징

 

l 어플리케이션 리소스 관리 및 스케줄링

l분산시스템 커널

l10000개 노드까지 확장가능

l기본 Docker 지원

l multi-tenancy

l fault-tolerance, HA

l 확장성

   

DCOS는 커널레벨에서 분산환경을 지원하는 mesos를 좀더 매끄럽고 유연하게 마치 하나의 컴퓨터를 다루듯이

분산 Datacenter의 자원을 손쉽게 관리하고kafka spark 등 여러 데이터 서비스를 손쉽게 설치 및 관리가 가능하도록 도와주어 마이크로 서비스 환경에 최적화된 운영체계입니다.

DCOS를 쓰면 기존 장비 효율성을 4배로 향상시켜줄 수 있으며, 자동화된 스케쥴러 및 워크로드 다중 처리는 손쉽게 데이터센터 를 다룰 수 있습니다.

 

DC/OS 특징

다양한 실행환경

사내 서버들에 적용할 수 있으며, Amazon,Azure등 클라우드 환경에도 적용할 수 있습니다. 심지어 개인 PC에서 테스트 목적으로 설치할 수 있습니다.

강력한 리소스 관리

메모리,CPU,네트워크 자원을 각 서버마다 작업부하를 조정하고 리소스 공유를 통해 자원 활용도를 높입니다.

가상 네트워크 오버레이

가상 IP를 컨테이너 마다 부여하고 동적으로 할당 및 조정이 가능하여 완벽한 가용성을 제공합니다. 

동적분산 로드밸런싱

트래픽 과부하 상태에 따라 자동 로드 밸런싱 

자가 치유 인프라스트럭처

부하 장애시 자동 감지 자동복구 

무중단 업그래이드

전체적 서비스 중단없이 서비스 배포 및 업그래이드가 가능합니다. 

UNIVERSE

DCOS의 강력한 기능으로 스마트폰의 google play는 앱스토어 처럼 DCOS환경용 어플리케이션을 손쉽게 설치하고 업그레이드 할 수 있다.

   

    [DCOS 환경에서 손쉽게 설치할 수 있는 각종 어플리케이션]

 

활용범위

  • 개인화 서비스 기계학습, IoT 신속한 서비스 개발 및 배포

  • 마이크로 서비스 아키텍처 웹 개발

  • 대규모 사용자 서비스 지원

  • Private/Public Cloud 혼용을 위한 Hybrid Cloud 환경 

  • 손쉬운 GPU 기반의 AI 환경 구성

  • 빅데이터 처리

     

다음에는 DCOS를 설치하는 방법 및 다양한 최신 분산 어플리케이션을 설치해보며 이용하는 것에 대해 계속 연재해 보도록 하겠습니다.

New Multi-Channel Dynamic CMS

간략하게 알아보는 추천시스템


이번에는 추천시스템에 대해 간략하게 알아보겠습니다.


추천시스템은 Content-basedCollaborative Filtering으로 크게 두 가지로 나뉠 수 있습니다.

Content-based는 말 그대로 추천하고자 하는 아이템에 대한 정보를 기반으로 추천하는 알고리즘입니다. 영화를 예로 들면 특정 배우 혹은 장르와 같은 아이템의 정보들을 기준으로 추천을 합니다. 많은 사용자의 이용 정보 없이도 충분히 추천이 가능하지만 모델링 방식에 따라 정확도가 많이 달라지고, 비슷한 아이템끼리만 추천이 가능하여 추천 범위가 제한되는 단점이 있습니다.

Collaborative Filtering는 위와 같이 영화를 예로 들면 해리포터를 좋아하는 A와 성향이 비슷한 B역시 해리포터를 좋아 할 것이라는 것을 활용한 기법으로 아이템 또는 사용자 간 유사도에 중점을 둔 추천시스템이며 가장 많이 쓰이는 알고리즘 중 하나입니다. 정확도가 content-based보단 비교적 좋고 사용자의 행동 패턴에 따라 적절한 추천이 가능합니다. 하지만 수집된 정보의 양이 많아야 좋은 결과가 나오는 단점이 있습니다.

 

Collaborative filtering도 두 가지로 나뉠 수 있는데 item-based CFuser-based CF가 있습니다.

 

쉽게 설명하자면 item-based는 상품 간의 유사도를 기반으로 콜라를 자주 사먹는 사람에게 콜라와 비슷한 탄산음료를 추천하는 기법이며 user-based는 유저 간의 유사도를 기반으로 상품을 추천하는 것을 예로 피자와 파스타를 먹는 사람들이 주로 탄산음료를 같이 먹기 때문에 피자를 구매 시 탄산음료를 추천하는 기법입니다..

 

유사도를 계산하는 알고리즘은 유클리디안(Euclidean) 거리 점수 기반,코사인(Cosine) 기반,자카드 계수 (Jaccard) 기반, 피어슨 상관계수, 맨해튼 거리 등 여러 가지가 있습니다.

 

CF에 대해 간단히 알아보았으니 영화 관람 여부를 기반으로하여 item-based CF로 간단한 영화 추천을 해보려고 합니다.


영화 관람 여부는 아래와 같습니다.

영화의 관람여부를 true 1 false 0으로 정하도록 하였습니다.

 

Lord of the Rings

Man of Steel

INCEPTION

Avengers

John

1

0

1

0

Peter

0

1

0

1

Sam

0

0

1

1

Nolan

1

1

0

1

Derrick

1

0

1

0

john에게 영화를 추천하려고 합니다. 보지 않은 영화인  man of steel avengers 중 어떤 것부터 추천해야 할지 알아보도록 하겠습니다.

보았던 영화들과 보지 않은 영화의 유사도를 구해보려고 합니다. 먼저 Man of Steel과 Lord of the Rings 의 유사도를 먼저 구하려고 합니다.

 

Lord of the Rings

Man of Steel

INCEPTION

Avengers

John

1

0

1

0

Peter

0

1

0

1

Sam

0

0

1

1

Nolan

1

1

0

1

Derrick

1

0

1

0

 두 영화의 유사도는 코사인 유사도를 이용하여 구하겠습니다.

각 영화를 벡터화를 시키면 Lord of the rings [1,0,0,1,1] Man of Steel [0,1,0,1,0]이 됩니다.

코사인 유사도는 두 단위 벡터의 내적을 이용해서 벡터 간의 내각의 크기로 유사도를 측정합니다.

측정값은 0 1사이의 값을 가지며 해당 값의 의미는 0에 가까울수록 일치하는 것이 없다고 보며 1에 가까울수록 일치하는 것이 많으며 1일 때 완전히 같은 값이고, 0일 때 서로 일치하는 것이 하나도 없다고 봅니다.

수식은 다음과 같습니다.


벡터 계산이 좀 쉽도록 numpy라이브러리를 이용하여 간략하게 두 영화의 유사도를 비교하면 다음과 같습니다

두 영화 간의 유사도가 0.41 정도가 나왔습니다이젠 Man of Steel John이 보았던 다른 영화(INCEPTION)와 다시 비교를 합니다결과는 0으로 나옵니다보았던 모든 영화와 비교해서 나온 결과를 합산한 값이 추천의 지표가 됩니다이제 보지 않았던 avengers에 대해서도 Man of Steel과 똑같이 관람했던 영화들과의 유사도의 합을 구해봅니다.

결과는

Man of Steel과의 유사도

Lord of the Rings : 0.408248290464

INCEPTION : 0

Man of Steel의 추천 점수 : 0 + 0.408248290464

Avengers와의 유사도

Lord of the Rings : 0.333333333333

INCEPTION : 0.333333333333

Avengers 의 추천 점수0.333333333333 + 0.333333333333 = 0.666666666667

 

Lord of the Rings

Man of Steel

INCEPTION

Avengers

John

1

0.408

1

0.666

Peter

0

1

0

1

Sam

0

0

1

1

Nolan

1

1

0

1

Derrick

1

0

1

0


점수가 높을수록 기존의 영화들과의 연관성이 높다고 판단하기 때문에 john에게는 avengers를 먼저 추천하는 결과를 얻을 수 있습니다.




New Multi-Channel Dynamic CMS

[Spark] Streaming에서 DataFrame Tip

 이번 시간에는 Spark Streaming을 사용할 때 데이터를 처리하고 모으는 부분에서의 팁을 공개하려고 합니다. Spark Streaming으로 프로그램을 하면 보통 sql을 사용하기 위하여 DataFrame에 많이 넣으실 텐데요. 오늘은 그 부분에 대한 Tip을 공개합니다.


한줄로 팁을 요약하면, "DataFrame에 테이블의 데이터를 유지시키고, 추가 시키자!" 입니다. 


보통 Dataframe의 createOrReplaceTempView 함수를 쓰면, 기존의 내용은 날라가고, 현재의 내용만 남게 됩니다. 그걸 방지하고자 다음과 같은 함수를 미리 선언합니다. 

 사실상 이 함수가 첫번째 핵심입니다. 2개의 DataFrame을 하나로 합쳐줍니다. 


 그리고 또 하나의 변수가 있습니다. "Broadcast"라는 변수 입니다.  

https://spark.apache.org/docs/2.2.0/rdd-programming-guide.html#broadcast-variables 

여기의 설명에는 이렇게 나와있습니다.


Broadcast variables allow the programmer to keep a read-only variable cached on each machine rather than shipping a copy of it with tasks.

즉, Broadcast 변수를 사용하면, 읽기전용 데이터를 각각의 머신에 효과적으로 복사할 수 있습니다. 한마디로 분산되서 돌아가고 있는 작업서버들에게 공용변수를 넣어주는 것 같은 효과를 내는것입니다. 


 이제 예를 들겠습니다. 저는 Record라는 case class를 선언했습니다.

 시간과 double형 결과값을 저장하기 위해서 사용합니다. 그리고, DataFrame에 계속 이 데이터를 append해서 저장할 것 입니다.  


 간단한 Spark Streaming을 만드는 프로그램을 예제를 찾아서 이미 알 것 이라고 생각하고, 저희 소스의 일부분만 캡쳐해서 보여 드리도록 하겠습니다. 

 여기가 output_df 라는 DataFrame을 처음에 생성하고, broadcast 변수로 선언하고, View를 만드는 코드 입니다. 

 

 그리고 Streaming을 돌면서 처리되는 안에서 위와 같이 정의하였습니다. finalValue는 Double형 최종 값이고, 아까 위에서 broadcast에서 정의했던 output_df 라는 DataFrame에 unionByName이라는 함수를 써서 append 시켰습니다. 


이제 메인코드는 다 끝났습니다. 실제 돌려진 결과물을 확인하겠습니다.  


첫번째 사진은 시작하자마자 아직 2초가 가기전, 빈데이터가 있을때 입니다. 


2,3번째 화면은 시간이 지남에 따라 계속 Table에 데이터가 추가되는 모습입니다. 





Storm + Kafka 연동하기

Spark 개발환경 구축 - Zeppelin Spark Interpreter에 HBase 연결하기  

Spark 개발환경 구축 - Scala, Intelij, Maven



 

New Multi-Channel Dynamic CMS

Apache Phoenix 활용

Apache Phoenix 활용

 


Apache PhoenixNoSQL의 한 종류인 HBase 위에 관계형 데이터베이스에서 사용하는 SQL layer를 구현한 오픈 소스의 개발 도구입니다. 이번 포스팅에서는 Apache Phoenix의 주요 특징과 Phoenix를 웹서비스 어플리케이션에 적용해 보면서 느꼈던 장점 및 한계점과 활용방안에 대해 알아보겠습니다.

 

1.1 Apache Phoenix의 특징

Phoenix는 우리에게 익숙한 SQL 문법을 사용하여 HBase 데이터에 접근한다는 것과 HBase Java 클라이언트 API 대신 표준 JDBC API를 사용한다는 특징을 갖고 있습니다. 이를 통해 테이블 생성, 데이터 삽입, 데이터 쿼리 등의 모든 CRUD DDL 작업을 수행할 수 있습니다. SQL JDBC의 사용은 사용자가 작성해야 하는 코드의 양을 줄여주고, 사용자가 알기 쉽게 성능 최적화되어 있습니다.

Phoenix의 주요 특징으로는 다음 3가지가 있습니다. 첫 번째로는 HBase 데이터에 대한 빠른 접근이 가능하다는 점입니다. Phoenix HBase에 특화된 push down 기능이 있습니다. 이 기능을 통해 Map-reduce를 사용하지 않고 사용자가 작성한 SQL 쿼리를 수신하여 native HBase 명령어로 컴파일하여 쿼리를 수행하게 됩니다. 두 번째는 Phoenix는 추가적인 서버를 필요로 하지 않기 때문에 비교적 가볍다는 것입니다. 마지막으론 Phoenix를 통해 기존에 존재하는 HBase 테이블과의 Mapping이 가능하다는 점입니다.

 

1.2 장점

HBase에서는 put, get과 같은 단순한 명령어만 사용할 수 있기 때문에 HBase 데이터에 대해 SQL 문법으로 쿼리할 수 있는 기능을 제공하는 Phoenix를 사용함으로써 아래와 같은 장점을 발견할 수 있었습니다.

 

1.2.1 JOIN

원래 HBase에서는 JOIN 기능을 지원하지 않아 데이터 모델링 단계에서 테이블을 비정규화 하거나, Application Side Join을 실시해야 했습니다. 하지만 Phoenix를 사용하게 된다면 기존에 저희가 익숙한 SQL 문법으로 JOIN 기능을 구현할 수 있습니다.

 

1.2.2 페이징 처리

게시판을 구현할 때 필수적인 기능이 바로 페이징 처리입니다. HBase 자체적으로 페이징 처리를 구현할 수 없는 것은 아니지만 Phoenix를 통해 SQL 키워드 중 ‘LIMIT OFFSET’을 이용하여 페이징 처리를 보다 손쉽게 구현할 수 있습니다.

 

1.2.3 키워드 활용

SQL에서 사용할 수 있는 여러 가지 키워드(DISTINCT, UPPER )를 활용할 수 있기 때문에 어플리케이션 단에서 처리해야 하는 로직을 줄일 수 있습니다.

 

1.3 한계점

Phoenix HBase 데이터에 대하여 SQL 문법을 활용한 쿼리 기능을 지원하긴 하지만, RDB 처럼 모든 기능을 제공하지는 못합니다. 웹서비스에 필요한 쿼리를 Phoenix를 통해 사용해 보면서 발견한 몇 가지 한계점은 아래와 같습니다.

 

1.3.1 서브쿼리 사용의 제한

Phoenix에서 FROM절 뒤에 서브쿼리를 사용하는 것은 가능하지만 SELECT 절 뒤에 서브쿼리를 사용하는 중첩 쿼리(Nested Query)’는 사용이 불가능합니다.

 

1.3.2 중첩 집계 함수 (Nested Aggregate function) 사용 불가능

함수 안에 또 다른 함수를 사용하는 것을 중첩 집계 함수라고 합니다. 예를 들어, 특정 컬럼의 데이터 갯수를 구하고 그 합계의 평균을 구하기 위해선 AVG(COUNT(컬럼명)) 과 같은 구문을 작성해야 합니다. 그러나 Phoenix에서는 이와 같은 중첩 집계 함수 사용이 불가능합니다.

cf) COUNT(DISTINCT 컬럼명)과 같이 함수와 키워드의 중첩 사용은 가능합니다.

 

1.3.3 키워드 및 함수 사용의 제한

Phoenix에서는 기존 SQL 함수 및 키워드 중 사용이 불가능한 것들이 몇 가지 있습니다.

 

1) CONVERT() 함수

CONVERT 함수는 특정 컬럼의 데이터 형식을 다른 데이터 형식으로 변환하는데 사용됩니다. 보통 날짜 데이터를 가지고 있는 컬럼을 대상으로 사용되며, 해당 날짜 컬럼에서 년도, , 일을 분리하여 새로운 컬럼으로 이용하기 위해 주로 사용합니다. Phoenix에서는 이러한 기능을 제공하는 CONVERT() 함수를 사용할 수 없습니다.

 

2) OVER() 함수와 RATIO_TO_REPORT() 함수

OVER() 함수는 여러 집계 함수들과 함께 사용되어 괄호 안의 내용을 기준으로 묶어주는 역할을 합니다. 주로 사용되는 OVER() 함수의 사용 형태는 다음과 같습니다.


OVER() 함수는 분석 쿼리를 만드는데 많이 사용되곤 하는데 Phoenix에서는 이 OVER() 함수를 사용할 수 없기 때문에 분석 쿼리를 만드는데 제한이 됩니다.

RATIO_TO_REPORT() 함수는 분석함수로서 값의 그룹별 합에 대한 값의 비율을 계산합니다. 이 함수를 통해 전체 중에 각 그룹이 차지하는 비율 등을 계산할 수 있는데 Phoenix에선 이 함수 또한 사용이 불가능합니다.

 

1.4 활용방안


1.4.1 CRUD 어플리케이션 구축

put get 명령어만을 이용하여 HBase 데이터에 접근할 때와는 달리 Phoenix를 사용하게 된다면 우리에게 익숙한 SQL 문법을 통해 HBase 데이터에 접근할 수 있습니다. 또한 SQL 키워드 및 함수들을 활용하여 페이징 처리와 조건 검색, JOIN 등을 할 수 있습니다. 이러한 Phoenix의 사용을 통해 SQL 접근 기능과 함께 HBase의 확장성을 필요로 하는 CRUD 기능의 어플리케이션을 구축하는데 효과적일 것이라고 생각합니다.

 

1.4.2 데이터 분석 기능 사용의 제한

Phoenix에서는 중첩 쿼리나 중첩 함수의 사용이 불가능하다는 점과 몇 가지 함수 및 키워드를 사용할 수 없다는 것을 알게 되었습니다. 또 그 외에도 여러 분석 함수들의 사용이 Phoenix를 통해서의 사용이 제한됩니다. 이와 같은 것들을 고려해보면 Phoenix를 이용하여 로그 데이터 분석과 같은 기능을 구현하는 데에는 어려움이 있을 것이라고 생각합니다.

 



 

'빅데이터' 카테고리의 다른 글

간략하게 알아보는 추천시스템  (0) 2017.12.29
[Spark] Streaming에서 DataFrame Tip  (0) 2017.11.30
Apache Phoenix 활용  (0) 2017.11.28
NoSQL 데이터 모델링  (0) 2017.10.30
HBase 개념 정리  (0) 2017.09.21
NoSQL 개념 정리  (0) 2017.09.21

New Multi-Channel Dynamic CMS

NoSQL 데이터 모델링


NoSQL 데이터 모델링

기존에 우리가 많이 사용하고 있는 RDMBS NoSQL은 전혀 다른 성격을 갖고 있고, 모델링 접근 방식 또한 다릅니다. 이 글에서는 먼저 NoSQL의 특징에 대해 알아보고, NoSQL의 데이터 모델링 패턴과 데이터 모델링 절차에 대해 알아보겠습니다.


1.1 NoSQL 특징

NoSQL RDBMS와 다른 형태의 데이터 저장 구조를 총칭합니다. NoSQL의 특징을 RDBMS와 비교하여 살펴보겠습니다.


1.1.1 RDBMS vs NoSQL 특징 비교

구분

RDBMS

NoSQL

데이터의 관계

Foreign Key 등을 이용하여 데이터의 관계를 정의한 후 JOIN 등의 관계형 연산을 수행

데이터 간의 관계를 정의하지 않음

확장성

데이터의 무결성 및 정합성 보장하기 위해 정규화된 데이터 모델을 사용하기 때문에 JOIN이 필요한 경우 확장성을 제약

데이터 모델 자체가 독립적으로 설계되어 있어 데이터를 여러 서버에 분산 시키는 것이 용이

스키마

스키마 변경에 따른 추가 작업이 필요함

유연한 스키마(Schema-less) 구조를 취함으로써 다양한 형태의 데이터를 저장할 수 있음


1.2 NoSQL 데이터 모델 구조

데이터 모델링을 하기 전에, 먼저 NoSQL이 어떤 구조로 데이터를 저장하는 지 이해할 필요가 있습니다. NoSQL의 데이터 모델 구조는 다음과 같이 구분될 수 있습니다.


1.2.1 Key/Value Store

Key/Value Store, 고유한 Key에 하나의 Value를 가지고 있는 형태를 의미합니다. Put(key, value) 명령어를 이용하여 데이터를 input하고, get(key) 명령어를 이용하여 데이터를 output 합니다

이 형태의 데이터 모델을 사용하는 DB로는 Redis가 있습니다.


1.2.2 Column Family Store

Key/Value Store 방식에서는 하나의 Key에 하나의 Value만 저장할 수 있다는 한계점이 있습니다. 이러한 단점을 극복한 것은 Column Family Store 방식입니다. 하나의 Key에 여러 개의 Column을 저장하고, Column-Value의 묶음을 Column Family 라고 합니다.


1.2.3 Ordered Key/Value Store

Key/Value Store의 확장된 형태로서, 데이터를 저장하는 방식은 동일하지만 데이터가 내부적으로 Key를 기준으로 Sorting되어 저장되는 기능을 갖고 있습니다. NoSQL은 데이터를 정렬(Order By)해주는 기능을 제공하고 있기 않기 때문에, 데이터를 Sorting하여 활용할 수 있다는 점은 NoSQL의 성능을 향상 시킬 수 있습니다.

이 형태의 데이터 모델을 사용하는 DB로는 HBase, Cassandra 등이 있습니다.


1.2.4 Document Key/Value Store

Key/Value Store의 확장된 형태로 Key에 해당하는 Value 필드에 데이터를 저장하는 구조는 동일하지만, 저장되는 Value의 데이터 타입으로 Document라는 구조화된 데이터 타입(JSON, XML, YAML )을 사용하는 것을 특징으로 하고 있습니다. 이를 통해 복잡한 계층 구조 표현을 가능하게 하고, 제품에 따라서는 Sorting, Join, Grouping과 같은 RDBMS에서 제공하는 기능을 제공합니다.

이 형태의 데이터 모델을 사용하는 DB로는 MongoDB, CouchDB, Riak 등이 있습니다.


1.3 NoSQL 데이터 모델링 패턴

NoSQL 데이터 모델링을 할 때, 가장 기본적으로 사용되는 패턴으로는 다음 3가지가 있습니다.


1.3.1 Denormalization (비정규화)

Denormalization은 같은 데이터를 중복해서 저장하는 방식입니다. 비정규화를 하면 테이블간의 JOIN을 없앨 수 있습니다. NoSQL에서 두 테이블을 JOIN해서 데이터를 가져오는 로직을 구현하려면, 각각의 테이블에서 데이터를 가져와 어플리케이션에서 합쳐야 하기 때문에 2번의 IO가 발생하게 됩니다. 이 때, Denormalization을 적용하여 하나의 테이블에 JOIN될 데이터를 중복 저장하게 되면 1번의 IO로도 데이터를 가져올 수 있습니다.

Denormalization을 이용하여 중복을 허용했을 때의 장단점은 다음과 같습니다.

장점

· 쿼리 당 I/O 횟수 감소
· 쿼리 데이터 사이즈 감소
· 쿼리 수행 복잡도 감소

단점

·
전체 데이터 사이즈 증가
· 데이터 일관성 문제 발생 가능


1.3.2 Aggregation

대부분의 NoSQL에서는 기본적으로 유연한 스키마(Schema-less)’를 제공합니다. 이 속성은 rowKey만 똑같다면 각각의 row들이 꼭 같은 컬럼을 가질 필요도 없고, 데이터 타입도 모두 달라도 된다는 것을 의미합니다.

 예를 들어, 파일 정보 저장 시스템이 있다고 할 때, 이 시스템은 파일에 대한 정보를 저장하고, 음악, 사진, 동영상 등의 파일의 종류에 따라 추가적인 메타 정보를 저장합니다. 이때의 개체관계도는 다음과 같습니다.

일반적인 용도의 파일 이외에 특수한 용도로 만들어진 MP3, 사진, 영화 파일들에 대한 예외 처리가 쉽지 않을 것입니다. 여기에 NoSQLSchema-less 속성을 적용하면 데이터 모델을 하나의 테이블로 합칠 수 있습니다.

이와 같이 1:N과 같은 복잡한 개체들의 관계를 손쉽게 하나의 테이블로 바꿀 수 있고, 이는 결과적으로 JOIN의 수를 줄여 쿼리 성능을 높일 수 있게 됩니다.


1.3.3 Application Side Join

NoSQL Join 기능을 제공하지 않기 때문에 Denormalization이나 Aggregation 등의 데이터 모델링 패턴을 이용하게 됩니다. 하지만, 이러한 패턴을 적용하더라도 어쩔 수 없이 Join 기능을 구현해야 하는 경우가 있습니다. 이 때는 NoSQL의 쿼리로는 불가능하고, NoSQL을 사용하는 client Application 단에서 Join 로직을 처리해줘야 합니다.

예를 들어, 2개의 테이블 TABLE 1, 2이 있고 TABLE 1의 컬럼 중 하나가 Foreign Key로서 TABLE 2의 데이터를 가리키고 있다고 할 때, Application Side Join을 수행하려면 TABLE 1에서 Primary Key로 한 row를 읽어온 후에, TABLE 2를 가리키는 컬럼의 값을 Key로 하여 다시 TABLE 2에서 쿼리를 해야 합니다.

이 방법은 Join이 필요한 테이블의 수 만큼 NoSQL로의 Request/Response IO가 발생하긴 하지만, Denormalization 등에 비해서 스토리지 사용량은 감소시킬 수 있습니다.


1.4 RDBMS NoSQL의 데이터 모델링 절차 비교

데이터 모델링이란, DB에 저장할 데이터들의 구조를 정의하는 작업을 의미합니다. NoSQL RDBMS와 특성이 매우 다르기 때문에 접근 방법을 바꿔 데이터 모델을 설계해야 합니다.


1.4.1 RDBMS 데이터 모델링 (개체 모델 지향)

RDBMS는 먼저 저장하고자 하는 도메인 모델을 분석합니다. 이를 통해 개체 간의 관계를 식별하여 테이블을 설계합니다. RDBMS는 다양하고 복잡한 쿼리를 지원하기 때문에 테이블을 디자인한 후에 필요한 데이터를 가져올 수 있도록 쿼리를 작성합니다. 테이블 설계 시 테이블간 데이터 중복을 최소한으로 하는 정규화된 테이블을 설계합니다.


1.4.2 NoSQL 데이터 모델링 (쿼리 결과 지향)

어플리케이션의 특징적인 데이터 접근 패턴에 따라 데이터 모델링을 실시합니다. NoSQL은 매우 단순한 쿼리만을 지원하기 때문에 어떤 쿼리 결과가 필요한 지 먼저 정의한 다음, 그 결과를 얻을 수 있도록 테이블을 디자인해야 합니다. 테이블(데이터 저장 모델) 설계 시 데이터가 두 개 이상의 테이블에 중복되게 저장하는 비정규화된 테이블을 설계해야 합니다.


1.5 NoSQL 데이터 모델링 절차


1.5.1 도메인 모델 파악

가장 먼저, 저장하고자 하는 도메인을 파악해야 합니다. 어떤 데이터 개체들이 있고 그 개체들간의 관계는 어떻게 되는지 등을 분석하고 ERD(개체관계도)를 그려서 도식화합니다. 이러한 방식이 RDBMS의 데이터 모델링 접근 방법이긴 하지만, NoSQL도 저장할 데이터에 대한 명확한 이해 없이는 제대로 된 데이터 모델이 나올 수 없을 것입니다.

이해를 돕기 위해 간단한 블로그 시스템을 예를 들어 설명하겠습니다

이 블로그 시스템은 사용자 아이디(userID)를 기반으로 블로그의 분류(Category)를 가지고 있고, 분류 별로 글을 작성할 수 있습니다. 또 글에 파일을 첨부(Attachment)할 수 있는 기능과 댓글(Comment)을 달 수 있는 기능이 있습니다.


1.5.2 쿼리 결과 (데이터 출력 형태) 디자인

다음으로 가장 중요한 과정인 쿼리 결과 디자인입니다. ‘도메인 모델을 기반으로 어플리케이션에서 쿼리가 수행되는 결과 값을 먼저 정합니다. 기본적으로 게시물을 등록하는 블로그 시스템에서는 다음과 같은 기능들이 필요할 것입니다.

(1) 블로그 사용자의 포스팅 분류명들을 목록으로 출력합니다.
(2)
포스팅 출력화면에는 상단에 포스팅의 분류명과 제목을 출력하고, 다음으로 포스팅 날짜와 본문 내용을 출력합니다.
(3)
첨부파일의 업로드 날짜와 파일명을 출력하고, 파일에 대한 링크를 출력합니다.
(4)
댓글에는 작성일과 작성자 이름, 댓글 내용을 입력하고, 작성자 이름에는 이메일을 링크합니다.

이러한 기능들을 구현하기 위해 필요한 쿼리들을 정의하고 난 뒤, 해당 쿼리의 출력 데이터를 기반으로 한 테이블들은 다음과 같을 것입니다.

NoSQL 데이터 모델링은 도메인 모델을 중심으로 하는 것이 아니라, 이 어플리케이션의 데이터 출력 내용을 기반으로 하기 때문에 쿼리 결과 디자인 과정이 가장 중요합니다


1.5.3 패턴을 이용한 데이터 모델링

쿼리 결과 디자인을 바탕으로 NoSQL에 정의될 데이터 모델링을 실시합니다. NoSQL Sorting, Grouping, Join 등의 RDBMS의 기능을 제공하지 않기 때문에, 이를 배제하고 Put/Get 명령어로만 데이터를 가져올 수 있는 형태로 NoSQL 내의 테이블을 재 정의해야 합니다.

이 때, 위에서 설명한 여러 가지 NoSQL 데이터 모델링 패턴들이 적용됩니다. 그 중 가장 중요한 것이 바로 Denormalization입니다. 데이터를 가급적 중복으로 저장하여 한 번에 데이터를 읽어오는 횟수를 줄여야합니다.

위의 블로그 시스템 데이터를 일반적인 NoSQL 스타일로 바꾸면 다음과 같습니다.

Key를 구성할 때, Posting 테이블에서 Join을 없애기 위해서 userID postID‘:’로 구분되는 deliminator로 하여 Key에 포함시켰습니다. 이렇게 했을 때 Ordered Key/Value Store의 경우에는 Key를 기반으로 Sorting을 하기 때문에 다음 2가지 기능을 사용할 수 있게 됩니다.

1) Sorting
postID를 순차적으로 증가시키게 되면, 같은 사용자의 글의 경우에는 정렬이 됩니다.

2) Grouping
포스팅을 출력하는 사용자에 대해서는 순차적으로 포스트를 출력하다가, 해당 사용자의 포스팅 데이터가 끝나면, Key의 앞부분인 userID가 다른 사용자ID로 바뀌기 때문에 where 문장 없이도 특정 사용자의 포스팅을 순차적으로 출력할 수 있습니다.


1.5.4 기능 최적화

Attachment 테이블의 경우, 포스팅이 되었을 때 레코드가 추가되며 변경이 거의 없습니다. 그리고 첨부파일의 수는 그리 많지 않기 때문에 하나의 필드에 모두 몰아서 저장할 수 있습니다. 이와 같이 하나의 필드에 여러 개의 데이터를 저장할 경우에는 Document Store을 고려해 볼 수 있을 것입니다.

또한 블로그 포스트, 첨부파일, 댓글은 정렬이 되어야 하기 때문에 Ordered Key 형태가 필요합니다. 지금까지의 데이터 모델은 포스팅이 된 순서대로만 출력한 형태인데, 분류 개념이 있기 때문에 분류에 따라서 포스팅을 출력하려면 분류 필드가 별도 필드로 들어가야 하고, 이 필드에 따라 where 문으로 select할 수 있는 기능이 있어야 합니다. RDBMS Index와 같은 이 개념을 NoSQL에서는 ‘Secondary Index’라고 합니다.

이런 옵션들을 적용해 보면 Posting 테이블은 아래와 같이 변경될 수 있습니다.


1.5.5 NoSQL 선정 및 테스트

그 다음으로는 모델링한 데이터 구조를 효과적으로 실행할 수 있는 NoSQL을 찾아야 합니다. NoSQL에 대한 구조 및 특성을 분석한 후에 실제로 부하 테스트, 안정성, 확정성 테스트를 거친 후에 가장 적절한 솔루션을 선택해야 합니다.

경우에 따라서는 여러 개의 NoSQL을 복합적으로 사용해야 할 경우도 있습니다. 또 하나의 NoSQL만으로 모든 데이터를 처리하지 말고, RDBMS와 혼용하거나 다른 NoSQL과 연동하여 최적의 시스템을 설계해야 합니다.


1.5.6 선정된 NoSQL에 데이터 모델 최적화 및 하드웨어 디자인

마지막으로 선정된 NoSQL을 기반으로 그에 적합하게 데이터 모델을 최적화해야 합니다. 그리고 이에 맞는 어플리케이션 인터페이스 설계와 구동시킬 하드웨어 디자인을 실시합니다.





'빅데이터' 카테고리의 다른 글

[Spark] Streaming에서 DataFrame Tip  (0) 2017.11.30
Apache Phoenix 활용  (0) 2017.11.28
NoSQL 데이터 모델링  (0) 2017.10.30
HBase 개념 정리  (0) 2017.09.21
NoSQL 개념 정리  (0) 2017.09.21
도커 공인 ip 설정  (1) 2017.08.04

New Multi-Channel Dynamic CMS

HBase 개념 정리

HBASE 란?

1.1 HBase 소개

Hadoop의 HDFS위에 만들어진 분산 컬럼 기반의 데이터베이스 입니다.

구조화된 대용량의 데이터에 빠른 임의접근을 제공하는 구글의  테이블과 비슷한 데이터 모델을 가지며, HDFS의 데이터에 대한 실시간 임의 읽기/쓰기 기능을 제공합니다.

사용자는 HBase나 HDFS에 직접 데이터를 저장 할 수 있고, 사용자는 데이터를 읽고 접근하는 것은 HBase를 통한 임의접근을 이용한다.


1.2 HBase

  • 선형 확장성이 있다.

  • 읽기와 쓰기의 일관성을 제공

  • 하둡과 연계하여 source가 되기도 하고 destination 되기도 한다.

  • 클러스터를 통한 데이터의 복제 제공


1.3 Architecture

  1.3.1 Master Server

    • Regionregeion 서버에 할당하고 할당 업무를 위한 zookeeper의 도움을 받는 작업을 수행
    • Region서버에 퍼져있는 region들의 로드밸런싱을 수행
    • 로드밸런싱 조율을 통해 클러스터의 상태 유지 수행


    • 테이블의 생성이나 column family의 생성과 같은 스키마의 변화나 메타데이터 연산을 책임진다.


  1.3.2 Regions Server

    • 클라이언트와 통신을 하고 데이터 관련 연산을 관리한다.
    • 내부 region의 읽기와 쓰기 요청을 관리한다.
    • Region의 크기는 region크기의 threshold에 의해 결정 된다.
    • 내부에 메모리 저장소와 HFile을 가지고 있다.
    • 메모리 저장소는 캐시와 같은 동작을 한다.


    • 처음 데이터를 저장하면 memstore에 저장이 되고 이후에 Hfile에 블록으로 저장 후 메모리는 Flush!


  1.3.3 Zookeeper

   • 설정 정보의 관리,  분산처리의 동기화 등을 제공해주는 오픈소스 프로젝트
    • 임시 노드를 다른 region server에게 제안하면 마스터서버는 가용서버가 있는지 확인 후 사용한다.
    • 가용성을 추가 하여 서버 실패나 네트워크 분할등을 추적할 수 있다.
    • 클라이언트가 region에 통신하려면 zookeeper을 통해야 한다.
    • Pseudo standalone모드에서는 hbase 자체가 zookeeper의 기능도 담당한다



1.4 HBASE vs RDBMS

RDBMS와 HBase 의 기능 및 주요 특징을 비교한다.

HBase

RDBMS

 스키마가 없다, 고정 컬럼 스키마의 개념이 없다. column families만으로 이용된다.

 테이블의 구조를 기술하는 스키마에의해서 이용된다.

 수평적으로 확장성이 있어 큰 테이블에 적합하다.

 확장하기 어려우며, 크기가 작은 테이블을 위해 생성 되었다.

 Hbase에는 Transaction이 존재하지 않음

 Transaction이 존재

 비 일반화된 데이터가 적재된다.

 일반화된 데이터가 적재된다.

 구조화된 데이터보다 덜 구조화된 데이터가 적합하다.

 구조화된 데이터에 적합하다.

 get / put / scan

 SQL

 MapRduce Join 활용

 Join에 최적화 됨

 Rowkey만 인덱스 지원

 임의 컬럼에 대한 인덱스 지원

 초당 수십만건 Read/Write

 초당 수천건 Read/Write

 단일로우 트랜잭션 보장

 다중 로우 트랜잭션 보장



1.5 HBase 용어설명

  1.5.1 Table 구조

 


용어

설명

Table

다중 로우로 구성된 집합

Row

HBase에서 한 로우는 로우 키와 하나 또는 그 이상의 칼럼과 값으로 구성된다로우는 저장될때 로우키를 기준으로 알파벳순으로 정렬되어 저장된다. 이러한 이유로 로우 키는 설계에서 매우 중요하다. 이러한 저장 방식은 연관된 로우끼리 가깝게 배치하려는 목적이다. 가장 일반적인 로우키의 패턴은 웹사이트 도메인이다. 만약 로우키가 도메인이라면 도메인 역순으로 저장할 수 있을 것이다. ( org.apache.www, org.apache.main). 이러한 방식으로 저장하면 테이블에서 모든 아파치 도메인은 근처에 저장되게 된다. 이러한 방식은 서브도메인의 첫글자를 기준으로 저장되는 것 보다 좋은 방식이 될 것이다.

Column

HBase 칼럼은 column family column qualifier로 구성된다. 해당 항목들은 콜론(:)으로 구분된다.

Column Family

컬럼 패밀리란 컴럼과 값의 집합을 성능상의 이유로 물리적으로 값은 장소에 배치한 것을 의미한다각 컬럼 패밀리는 저장된 프로퍼티의 집합을 가진다. 각 테이블로 로우는 주어진 컬럼 패밀리에 저장할 것이 없더라도 같은 칼럼 패밀리들을 가진다. 컬럼 패밀리는 테이블이 생성될때 명시되며, 내부 파일시스템에 저장되는 방식에 영향을 준다. 그러므로, 컬럼 패밀리는 스키마 설계에서 중요한 고려 사항이다.

Column  Qualifier

컬럼 수식어란 데이터를 인덱스를 제공하기 위해 컬럼 패밀리에 추가된 것이다. 주어진 컬럼 패밀리 content의 즉 컬럼 수석어는 content:html, content:pdf 일 수 있다. 컬럼 패밀리는 테이블이 생성될때 고정되지만, 컬럼 수식어는 로우간에 가변적이고 다를 수 있다.

Cell

셀은 로우, 컬럼패밀리, 컬럼 수식어의 집합이며, 값의 버젼을 표한하기 위해서 timestamp 값을 포함한다. 셀은 값은 해석되지 않은 바이트 배열이다.

Timestamp

Timestamp는 주어진 값의 버젼 식별자로서 각 값과 나란히 기록된다. 기본적으로 timestamp는 데이터가 기록될때 RegionServer의 시간이며, 셀에 데이터를 넣을때 명시할 수도 있다. Timestamp를 직접적으로 조작하는 것은 특별한 경우이며, 일반적인 경우에는 권장하지 않는다. 어플리케이션 레벨에서 timestamp를 인코딩하는 것은 권장하는 패턴이다.


  1.5.2 Put Method

구분

설명

Single Puts

 Put Instance를 생성하기 위해서는 row key를 제공해야 한다.

 HBaserow는 고유한 row key로 식별하며, row key 타입은 java 데이터 타입인 byte array로 저장된다.

 Column을 추가하려면 add( )를 사용한다.

 특정 cell이 존재하는지 알아보려면 has( )를 사용한다.

 클라이언트 코드에서 설정 파일에 접근하려면 HBaseConfiguration class를 사용한다.

KeyValue class

 Row 단위가 아닌 특정 cell 단위의 모든 정보를 반환한다.

 좌표계처럼 row key, column family, column qualifier, timestamp3차원 공간의 한 지점을 가리키는 모습이다.

 주로 KEY 데이터간의 비교/검증/복제 등에 사용한다.

 저장공간을 최소화하여 효율적으로 데이터 저장하고, 빠른 데이터 연산을 제공하기 위해 byte array 타입을 사용한다.

List of Puts

 연산을 일괄로 한데 묶어서 처리한다.

 리스트 기반의 입력은 서버 측에서 입력 연산이 적용 되는 순서를 제어 할 수 없다.

 데이터 입력 순서를 보장해야 하는 경우에는 작게 나눈 후 Write cache를 명시적으로 flush해야 한다.


  1.5.3 Get Method

구분

설명

Single Gets

 특정 row 하나를 대상으로 수행되지만 row 내에서는 column/cell 제한이 없다.

 버전 개수는 1로 최근 값만 리턴 받고, setMaxVersions( )를 통하여 지정 가능하다.

Result class

 get( )을 통하여 데이터를 읽어 들일 때 get 조건에 만족하는 모든 cell을 담고 있는 Result classinstance를 반환한다.

 서버에서 반환한 모든 column family, column qualifier, timestamp 접근 수단을 제공한다.

List of Gets

 하나의 요청으로 여러 개의 row를 요구할 때 사용된다.

 get instance와 동일한 배열을 반환, 예외발생 중 하나로만 동작한다.


  1.5.4 Delete Method

구분

설명

Single Deletes

 delete class를 생성하려면 삭제 대상 row key를 입력해야 한다.

 rowlock 파라미터를 추가 선택하여 동일한 row를 두 번 이상 변경하고자 할 때 사용자 자신의 락을 설정한다.

 전체 family 및 그에 속한 모든 column 삭제, timestamp 지정이 가능하다.

List of Deletes

 put list와 유사하게 동작한다.

 Remote 서버에서는 데이터가 삭제되는 순서를 보장할 수 없다는 것을 주의한다.

 table.delete(deletes) 수행 시 실패한 작업은 deletes에 남게 되며, Exception 처리는 try/catch 구문을 이용한다.



'빅데이터' 카테고리의 다른 글

Apache Phoenix 활용  (0) 2017.11.28
NoSQL 데이터 모델링  (0) 2017.10.30
HBase 개념 정리  (0) 2017.09.21
NoSQL 개념 정리  (0) 2017.09.21
도커 공인 ip 설정  (1) 2017.08.04
스마트의 시작, Ontology_4  (0) 2017.07.26

New Multi-Channel Dynamic CMS

NoSQL 개념 정리

NoSQL


빅데이터, AI, 딥러닝 등 기술적인 화두들의 공통점으로 대용량 데이터에 대한 저장을 생각할 수 있습니다. 그 중에서도 NoSQL은 기존의 RDBMS를 사용함으로 해서 발생할 수 있는 문제들의 해결방안으로 손 꼽을수 있을 것입니다.



1.1 등장 배경

웹 2.0 환경과 빅데이터가 등장하면서 RDBMS에서의 '데이터를 처리하는 데 필요한 비용의 증가' 이슈를 해소하기 위해 등장하였습니다.

관계형 데이터베이스를 사용하면서 기하급수적으로 증가하는 데이터의 저장을 위해서는 장비의 성능이 좋아야하고 이를 위해서 하드웨어적으로 큰 비용이 발생한다.



1.2 특징

  1.2.1 분산저장

    • 데이터와 트래픽이 증가함에 따라 기존의 수직적 확장에서 장비의 수를 늘리는 수평적 확장(Scale-out) 방식

    • 샤드 키(Shard key)를 기준으로 하나의 테이블을 수평 분할하여 서로 다른 클러스터에 분산 저장하고 질의


  1.2.2 Schema-less

    • 데이터의 구조를 미리 정의할 필요가 없으며, 시간이 지나더라도 언제든지 바꿀 수 있다.

    • 데이터베이스가 스키마를 직접 관리하지 않는 것을 위미할 뿐, 암묵적인 스키마는 여전히 존재한다.


1.3 CAP 이론


CAP 이론은 분산 시스템에서 보장해야 한느 3가지 특성으로 Consistency (일관성), Availability (유효성), Partition Tolerance (파티션 허용) 중 3가지를 동시에 만족시키는 것은 불가능 하고, 최대 2가지 특성만 만족시킬 수 있다는 이론으로 RDBMS의 경우 CA 특성을 만족합니다.



    • 일관성(Consistency) : 분산된 노드 중 어느 노드로 접근하더라도 데이터 값이 같아야 한다.
    • 가용성(Availability) : 클러스터링된 노드 중 하나 이상의 노드가 실패(Fail)라도 정상적으로 요청을 처리할 수 있는 기능을 제공한다.

    • 분산 허용(Partition Tolerance): 클러스터링 노드 간에 통신하는 네트워크가 장애가 나더라도 정상적으로 서비스를 수행한다. 노드 간 물리적으로 전혀 다른 네트워크공간에 위치도 가능하다.


1.4 NoSQL 데이터베이스 유형

  1.4.1 컬럼 형식 데이터베이스

컬럼 형식 데이터베이스는 데이터의 행이 아니라 데이터의 컬럼을 읽고 쓰는데 최적화된 데이터베이스 입니다.
컬럼 기반 스토리지는 전반적인 디스크 I/O 요구사항과 디스크에서 로드해야 하는 데이터의 양을 획기적으로 줄여주므로, 데이터베이스 분석 성능에 중요한 요소이다.

  1.4.2 도큐먼트 데이터베이스
도큐먼트 데이터베이스는 주로 JSON 또는 XML 형식의 문서와 같은 반정형 데이터를 저장하도록 설계된 데이터베이스 입니다.
기존 관걔형 데이터베이스와는 달리, 비관계형(NoSQL) 문서별로 다른 스키마를 적용할 수 있도록 좀 더 유연하게 스키마를 적용할 수 있습니다.

  1.4.3 그래프 데이터베이스
그래프 데이터베이스는 간선이라고 부르는 방향 링크와 정점을 저장합니다. 그래프는 관계형(SQL) 및 비관계형(NoSQL) 데이터베이스에 구축될 수 있습니다.
정점 및 엣지는 각각 이들과 연관된 속성을 가집니다.

  1.4.4 인 메모리 키-값 저장소
인 메모리 키-값 저장소는 읽기 중심의 어플리케이션 워크로드(소셜 네트워킹, Q&A포털 등) 또는 컴퓨팅 집약적 워크로드(추천 엔진 등)에 최적화된 NoSQL 데이터베이스 입니다.
인 메모리 캐싱은 핵심 데이터를 메모리에 저장해 액세스 지연 시간을 줄여주므로 어플리케이션 성능이 향상됩니다.




'빅데이터' 카테고리의 다른 글

NoSQL 데이터 모델링  (0) 2017.10.30
HBase 개념 정리  (0) 2017.09.21
NoSQL 개념 정리  (0) 2017.09.21
도커 공인 ip 설정  (1) 2017.08.04
스마트의 시작, Ontology_4  (0) 2017.07.26
Storm + Kafka 연동하기  (0) 2017.07.21

New Multi-Channel Dynamic CMS

도커 공인 ip 설정


<이미지 출처 : https://www.docker.com/docker-suse-linux-enterprise-server-sles >

docker를 사용하다 보면 컨테이너가 외부에서 실제 여러 머신이 동작하듯이 사용해야 할 경우가 생기곤 합니다. 그래서 이번 포스팅은 컨테이너에 정적으로 공인 IP를 할당하는 방법에 대해 알아보고 실제 해보았을 때 생기는 불편할 수 있는 점에 대해서 다루겠습니다.

docker 1.12.3버전을 이용하였습니다.

Host machine ip : 2**.***.***.36,  container ip : 2**.***.***.37


Docker network 생성 및 컨테이너 실행

docker에서 기본적으로 제공되는 network에서 macvlan이 사용이 가능해서 구성해보려고 합니다.

먼저 docker network를 생성해줍니다.


Network가 정상적으로 생성이 완료된 것을 확인했다면 실행을 해봅니다.

실행 시 --net --ip 옵션을 이용하여 고정 ip를 가지는 컨테이너를 실행 가능합니다.


2**.***.***.37라는 ip주소를 갖는 컨테이너를 생성합니다. 모든 것이 원활하게 동작 할 것이라고 생각했지만 불편한 점이 하나 발생 합니다.


한계

컨테이너 간 그리고 외부와의 통신은 원활히 이뤄지는데 docker 호스트 머신과 컨테이너 간의 통신이 불가능 하다는 단점이 있습니다.

실제로 호스트 머신에 ping을 날려도 응답이 전혀 없습니다.


Arp table을 보시면 mac주소 정보가 없고 Flags Mask complete가 아닌 상태에 있는 것을 확인 하였습니다.


근본적인 원인은 Docker network 생성시 macvlan 모드를 사용하면 커널모듈에서 필터링하여 호스트 머신에 접근이 불가능하도록 되어있습니다.해당 ip로 연결 시도는 되었지만 도달하지 못했기에 mac주소를 알지 못합니다.

*Flags Mask의 'C'는 온전하게 학습된 주소라는 의미를 가집니다.

접근불가는 컨테이너와 호스트 머신과의 격리 및 보안적인 이유가 큽니다만 꼭 호스트머신과 같은 레벨로 네트워크를 구성하고 상호간에 접속이 필요하다면 해결 책은 있습니다.


문제 해결 방법

macvlan을 쓰면서 컨테이너와 호스트 머신과의 통신이 필요하다면 기존의 인터페이스에 네트워크 인터페이스를 별도로 하나 더 macvlan 모드로 생성하고 docker network macvlan을 새로 생성한 인터페이스로 설정해주면 해결이 됩니다.


Mkif.sh

----------------------------------------------------------------------------------------------------

# mactest 인터페이스 구성

 

ip link add link ens33 mactest type macvlan mode bridge

ip address add 2**.***.***.36 dev mactest

ip link set dev mactest up

 

# 라우팅 테이블 작업

 

# 기존 라우팅 테이블의 정보 비우기

ip route flush dev ens33

ip route flush dev mactest

 

# 라우팅 정보 추가

ip route add 2**.***.***.0/23 dev mactest metric 0

 

# 라우팅 테이블에 게이트웨이 정보 추가

ip route add default via 2**.***.***.252

-------------------------------------------------------------------------------------------------------------


위 내용의 쉘 파일을 생성해주고 실행 권한을 준 뒤 실행을 시킵니다.


ip명령어를 이용하여 해당 network interface 정상적으로 생성되었는지 확인 해봅니다.


해당 network interface를 사용하는 docker network를 생성하고 확인 해봅니다.


새로 만든 docker network를 이용하는 컨테이너를 만들어보겠습니다. 처음 macvlan을 사용했던 같은 옵션으로 주시면 됩니다.


이제 정상적으로 컨테이너에서 로컬 머신으로 접속이 되는지 ping을 시도해보고 arp table도 확인해봅니다.


정상적으로 mac주소가 들어가 있으며 flags Mask C로 정상적으로 완료 되어있습니다.

이제 docker 호스트 머신에 접속이 안되었던 문제가 해결 되었습니다.


네트워크 성능 비교

네트워크 통신 구간에 가용한 네트워크 대역폭을 측정하는 Iperf3라는 툴로 네트워크 대역폭을 측정해서 컨테이너 사용 시 네트워크 성능이 얼마나 하락 하는지 그리고 각 네트워크 구성에 따라 어떻게 달라지는지 비교해 보고 마치겠습니다.

비교하는 기준은 localhost-localhost로하였고 container-container 통신들을 비교한 것입니다.

*성능이 좋지 않은 vm으로 하였기에 오차가 있을수도 있습니다.



'빅데이터' 카테고리의 다른 글

HBase 개념 정리  (0) 2017.09.21
NoSQL 개념 정리  (0) 2017.09.21
도커 공인 ip 설정  (1) 2017.08.04
스마트의 시작, Ontology_4  (0) 2017.07.26
Storm + Kafka 연동하기  (0) 2017.07.21
docker 이해  (0) 2017.07.07

New Multi-Channel Dynamic CMS

스마트의 시작, Ontology_4


“Ontology 관련 용어정리


 오늘은 Ontology를 공부하다 보면 자주 접하게 되는 다양한 용어(도구)들을 정리해보는 시간을 갖도록 하겠습니다. Ontology가 뭔지, 어떻게 적용할 수 있는지 이런 것들로 정신이 없을 때, (?)으로 우리 앞에 나타나 더 정신 없게 만들어주는 이들바로 RDF, OWL, SKOS,... 등의 다양한 용어들입니다. 이번 기회에 잘 정리해 둔다면 명확한 구분뿐만 아니라 실제 구현을 할 때 유용하게 선택적으로 사용할 수 있을 것입니다.


l   메타데이터 언어 : RDF , RDFS, OWL, ...

- RDF (Resource Description Framework)

 RDF W3C에서 웹에서 Ontology의 구현을 목적으로 개발한 메타데이터 언어(1999.02)URI를 가지는 자원

(Resource)을 정의하는 도구입니다

  (RDF elements)

     - Description, Statement, List, Property, ...

     - about, resource, object, subject, predicate, type, ...



- RDFS (RDF-Schema)

RDFS도 메타데이터 언어로 RDF로 정의된 자원들간의 관계를 정의하기 위한 도구입니다.

  (RDFS elements) 

     - Class, Container, Datatype, Literal, ...

     - domain, range, comment, label, subClassof, subPropertyOf, ...



- OWL (Web Ontology Language)

 OWL W3C에서 만든 메타데이터 언어(2002.02)RDF(S)의 부족한 표현력을 보다 더 풍부하게 하고자 많은 어휘들 추가하여 보완한 도구입니다.

  (OWL elements)

     - [(In)Equality]  equivalentClass, equivalentProperty, differentFrom, ...

     - [Restriction]   minCardinality, maxCardinality, allValuesFrom, someValuesFrom, ...

     - intersectionOf, inverseOf, oneOf, disjointWith, unionOf, ...



l   Ontology Vocabulary (어휘집) : FOAF, SIOC, SKOS, ...

 이제 사용자는 앞서 정리한 메타데이터 언어인 RDF(S) OWL로 독자적인 Ontology를 구현하는 것이 가능해졌습니다하지만 그것이 생각만큼 쉬운 일은 아닙니다. 왜냐하면 사용자에게는 모든 것을 일일이 다 정의해야 하는 버거움이 뒤따르기 때문입니다. 뿐만 아니라 사용자마다 독자적인 정의를 하는 부분이 많으면 많을수록 표준화와는 거리가 멀어지게 됩니다. 따라서 이러한 문제들을 덜어내고자 등장한 것이 ‘Ontology Vocabulary’입니다. 이름 그대로 Ontology구현시 자주 사용되는 어휘들을 미리 정의해 놓은 집합체로, 처음 생성자가 구현해 놓은 일종의 Ontology라고 할 수 있습니다.


- FOAF (Friend Of A Friend)

 2000년대 초기에 등장한 FOAF는 온라인 상에서 사람들의 관계를 표현하고자 만들어졌습니다. 따라서 소셜 네트워크에서 활용빈도가 높은 것으로 알려져 있습니다.

  (FOAF elements)

     - [Class] Person, OnlineAccount, Agent, Organization, Document,...

     - [Property] interest, knows, member, maker,...



- SIOC (Semantically Inter-linked Online Community)

 온라인 커뮤니티 사이트를 구조화하기 위해 구현된 Ontology FOAF와 결합된 형태로 많이 사용되고 있습니다.

  (SIOC elements)

     - [Class] Site, Role, Post, Container, Item, Space, ...

     - [Property] has_host, has_member, has_creator,...



- SKOS (Simple Knowledge Organization System)

 SKOS는 지식어휘체계를 정의하기 위해 등장한 Ontology로 유의어(Thesaurus), 분류체계(Taxonomy) 등을 구현하는데 유용하게 사용되고 있습니다. SKOS 이후 SKOS Core로 확장 개발되기도 하였습니다.

 (SKOS elements)

     - borader, related, prefLabel, altLabel, exactMatch, boardMatch, ...




 이렇게 크게 2가지로 분류되는 Ontology Tools을 간략하게 정리해보았습니다. 간략한 내용이었지만 이것만으로도

 Ontology 구현할 때 유용한 팁이 되어 훨씬 수월함을 느끼실 수 있으실 겁니다.




'빅데이터' 카테고리의 다른 글

NoSQL 개념 정리  (0) 2017.09.21
도커 공인 ip 설정  (1) 2017.08.04
스마트의 시작, Ontology_4  (0) 2017.07.26
Storm + Kafka 연동하기  (0) 2017.07.21
docker 이해  (0) 2017.07.07
스마트의 시작, Ontology_3  (0) 2017.06.30

New Multi-Channel Dynamic CMS

Storm + Kafka 연동하기

 실시간 처리를 위하여 Storm을 분석하고 있습니다.  

 Spark가 배치성 처리를 위한다면, Storm은 더욱 실시간성 처리가 가능할 것 같아서 분석중입니다. 실시간 처리를 하려면 일단 Kafka와 연결을 해야하는데, Storm의 홈페이지에는 별로 자세한 내용이 없고, 구글검색을 해도 정확하게 찾는 내용이 없는 것 같아 직접 글을 써볼까 합니다.


 저의 개발환경은 Spark와 마찬가지로 Intellij의 Maven을 활용합니다. 


새로운 java 프로젝트를 만듭니다. 저는 1.8 버전으로 만들었습니다. 그리고 pom.xml에 Dependency를 추가합니다 .

Storm으로 개발 할 것이기 때문에, storm-core를 넣고, 지난 spark때 사용했던 maven-shade-plugin도 추가합니다. 


<dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-core</artifactId>
<version>1.1.0</version>
<scope>provided</scope>
</dependency>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<filters>
<filter>
<artifact>*.*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META_INF/*.DSA</exclude>
<exclude>META_INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<finalName>${project.artifactId}-cyberx-${project.version}</finalName>
</configuration>
</plugin>
</plugins>


 그리고 이제부터가 헤맨 부분입니다.  

Kafka를 연동해야 하는데, 어떤 Dependency를 추가해야 할지 모르겠습니다. 

Storm의 문서를 찾아보니 http://storm.apache.org/releases/1.1.0/storm-kafka.html  여기에 Kafka 내용이 있습니다. 

 <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka_2.10</artifactId>
            <version>0.8.1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


이렇게 추가를 하면 된다는군요. 

저는 consumer를 사용할 것 이기 때문에 http://storm.apache.org/releases/1.1.0/storm-kafka-client.html 이 페이지의 내용도 추가하겠습니다. 

  <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>0.10.0.0</version>
        </dependency>


 그러면 이제 Kafka 개발할 준비가 되었습니다. 이제 Kafka가 실제로 잘 돌아가는지에 대한 예제 코드를 만들어보겠습니다. 실제 작업을 처리할 Bolt들 부터 만들겠습니다. 예제는 역시 WordCount가 만만하기 때문에 WordCount로 선택했습니다. 

(예제 소스는 https://www.tutorialspoint.com/apache_kafka/apache_kafka_integration_storm.htm 이곳을 참조 하였습니다)


 먼저 데이터를 스페이스로 구분하여 Split 하는 Bolt를 만듭니다. IRichBolt를 implements하고, 함수들을 선언하여야 합니다. 

import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;

import org.apache.storm.task.OutputCollector;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.IRichBolt;
import org.apache.storm.task.TopologyContext;

import java.util.Map;

public class SplitBolt implements IRichBolt{
private OutputCollector collector;


public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
this.collector = outputCollector;
}

public void execute(Tuple input) {
String sentence = input.getString(0);
String[] words = sentence.split(" ");

for(String word: words) {
word = word.trim();

if(word.length() != 0) {
word = word.toLowerCase();
collector.emit(new Values(word));
}
}

collector.ack(input);
}

public void cleanup() {

}

public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("word"));
}

public Map<String, Object> getComponentConfiguration() {
return null;
}
}

 실제 구현 부분은 execute 함수에 있고, declareOutputFields 함수에 "word"라는 필드로 선언하였습니다.  

 다음으로 Split되어 이제 한단어로 표시된 word들을 Count하는 Bolt를 만듭니다. 


package com.cyber.kafkaStorm;

import org.apache.storm.tuple.Tuple;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.topology.IRichBolt;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.task.TopologyContext;

import java.util.Map;
import java.util.HashMap;


public class CountBolt implements IRichBolt{
Map<String, Integer> counters;
private OutputCollector collector;


public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
this.counters = new HashMap<String, Integer>();
this.collector = outputCollector;
}

public void execute(Tuple input) {
String str = input.getString(0);

if(!counters.containsKey(str)) {
counters.put(str, 1);
} else {
Integer c = counters.get(str) + 1;
counters.put(str, c);
}

collector.ack(input);
}

public void cleanup() {
for(Map.Entry<String, Integer> entry:counters.entrySet()) {

    System.out.println(entry.getKey() + " : " + entry.getValue());
    }

}

public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {

}

public Map<String, Object> getComponentConfiguration() {
return null;
}
}

 counter를 Map<String, Integer> 형식으로 만들었고, 데이터가 없으면 단어와 카운트1을 저장하고, 데이터가 이미 존재하면 카운트만 1 증가시킵니다. 역시 execute 함수에 정의합니다. 

cleanup 함수는 작업이 최종 종료될 때 실행되는 함수 입니다. 여기서는 Map의 내용을 프린트 합니다. 



이제 Bolt들은 준비가 되었고, Spout과 Topology만 완성하면 됩니다. Spout은 Kafka가 되기 때문에 Topology만 만들겠습니다. 

import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.generated.AlreadyAliveException;
import org.apache.storm.generated.AuthorizationException;
import org.apache.storm.generated.InvalidTopologyException;
import org.apache.storm.topology.TopologyBuilder;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.storm.spout.SchemeAsMultiScheme;
import org.apache.storm.kafka.trident.GlobalPartitionInformation;
import org.apache.storm.kafka.ZkHosts;
import org.apache.storm.kafka.Broker;
import org.apache.storm.kafka.StaticHosts;
import org.apache.storm.kafka.BrokerHosts;
import org.apache.storm.kafka.SpoutConfig;
import org.apache.storm.kafka.KafkaConfig;
import org.apache.storm.kafka.KafkaSpout;
import org.apache.storm.kafka.StringScheme;


/**
* Created by hsbjjang on 2017-07-19.
*/
public class KafkaStormTopology {
public static void main(String[] args){
Config config = new Config();
config.setDebug(true);
config.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, 1);

String zkConnString = "주키퍼주소";
String topic = "토픽명";
BrokerHosts hosts = new ZkHosts(zkConnString);

SpoutConfig kafkaSpoutConfig = new SpoutConfig(hosts, topic, "/" + topic, UUID.randomUUID().toString());
kafkaSpoutConfig.bufferSizeBytes = 1024 * 1024 * 4;
kafkaSpoutConfig.fetchSizeBytes = 1024 * 1024 * 4;
kafkaSpoutConfig.scheme = new SchemeAsMultiScheme(new StringScheme());

TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("kafka-spout", new KafkaSpout(kafkaSpoutConfig));
builder.setBolt("word-spitter", new SplitBolt()).shuffleGrouping("kafka-spout");
builder.setBolt("word-counter", new CountBolt()).shuffleGrouping("word-spitter");

///* 배포 방식 바꾸기
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("KafkaStormSampleCyber", config, builder.createTopology());
try { Thread.sleep(10000); } catch (InterruptedException e) { } // waiting 10s
cluster.killTopology("KafkaStormSampleCyber");
cluster.shutdown();



}
}


중간에 "주키퍼주소", "토픽명" 부분은 자기 환경에 맞춰서 넣어주면 됩니다. 

kafka config를 만들어서 작성하고, Spout은 Kafka로, 그리고 Bolt들을 순서대로 연결해주었습니다. 

그리고 10초간 기다리다가 10초가 지나면 Topology를 종료합니다. 


Kafka Topic을 만들어서 아무 데이터나 넣고, Storm을 실행합니다. 저는 jar파일로 묶어서, 리눅스 서버에서 실행하였습니다.

storm jar jar파일명 패키지명.mainClass명

 

그러면 실행결과 가 나옵니다.

 

 

 

이상 Storm과 kafka 연동하여 WordCount 예제였습니다. 

 


 



 








'빅데이터' 카테고리의 다른 글

도커 공인 ip 설정  (1) 2017.08.04
스마트의 시작, Ontology_4  (0) 2017.07.26
Storm + Kafka 연동하기  (0) 2017.07.21
docker 이해  (0) 2017.07.07
스마트의 시작, Ontology_3  (0) 2017.06.30
Spark 개발환경 구축 - Zeppelin Spark Interpreter에 HBase 연결하기  (0) 2017.06.23

New Multi-Channel Dynamic CMS