Scale Up vs Scale Out

빅데이터를 이야기하면 빼놓을 수 없는 아키텍처이다. 간단하게 단일서버내에서 용량을 추가하는 방식을 Scale Up, 노드를 추가하여 확장하는 방식을 Scale Out으로 볼 수 있다. 서버급 장비는 비싸기도 엄청 비싸다. 하지만 데스크탑 서버급을 하나 붙이는 정도라면? 그렇게 부담스럽지 않다. 이렇게 Scale Out방식을 선택해서 출발하게 된것이 바로 빅데이터 처리기술의 대명사 분산파일시스템과 맵리듀스 이다.

Hadoop

과거에는 기가, 테라급의 데이터면 빅데이터라고 볼 수 있었지만 이제는 아니다. 페타바이트를 처리해야하는 상황이다. 하둡은 이론상 6000대 이상 클러스터 구성이 가능하다고 한다. 1테라 하드를 가진 컴퓨터 6000대를 연결하면 6페타바이트 확보가 가능하다. 또한 6000대의 컴퓨터가 병렬로 연산한다면? 슈퍼컴퓨터 뺨치는 성능이 나온다. 야후는 최근 4000노드를 이용하여 단일클러스터를 구상했고 디스크공간이 16페타라고 한다. -_-;; 대단하다

1. HDFS

구글분산파일시스템을 보고 구현한 오픈소스가 바로 HDFS이다. 기존 대용량 파일시스템과의 가장 큰 차이점은 저사양서버를 이용해 스토리지를 구성할 수 있다. HDFS에 저장하는 데이터는 물리적으로 분산된 서버의 로컬디스크에 저장되며 HDFS에서 제공하는 API를 이용해서 처리한다.

HDFS는 다음의 네 가지 목표를 가지고 설계되었다.

장애복구

데이터를 저장할 때 복제 데이터를 같이 저장

스트리밍 방식의 데이터 접근

데이터처리량 중점의 배치작업에 적합하게 설계됨

대용량 데이터 저장

하나의 파일이 테라바이트 이상의 크기를 저장할 수 있음

데이터 무결성

저장데이터는 수정이 불가능하고 읽기만 가능

HDFS가 기존의 모든 대용량 파일시스템을 완전히 대체할 수는 없다. 트랜잭션 처리가 중요한 경우에는 적합하지 않으며, 대용량 데이터 저장 및 배치처리시 권장된다.

또한 HDFS의 경우 데이터 복재와 분산저장이 이루어지기 때문에 저장공간에 대해서 별도 RAID구성이 필요없다.

2. Map Reduce

분석로직에 대해서 Map과 Reduce만 개발자가 적절히 개발하면, 데이터에 대한 분산과 병렬처리는 프레임워크가 처리하게 된다. 네임노드에서 신규 잡이 제출되면 Job Tracker에 의해서 작업이 추적되며 이는 다시 태스크로 잘게 쪼개져서 각 데이터노드로 전달된다. 데이터노드에서는 입력데이터를 스플릿으로 나누어 각 맵퍼가 실행되며, 맵퍼출력결과는 정렬과 병합을 거쳐서 리듀서로 전달된다. 리듀서는 특별히 지정되지 않으면 1개가 동작하며 출력데이터가 다시 HDFS에 저장이 된다. 이러한 방식의 네임노드가 모든 잡을 추적해야한다는 부담이 생겨서 2.0 에서는 YARN을 통해 개선된 아키텍처가 적용된다.


3. Common, YARN, 기타

Hadoop Common의 경우 공통성 유틸리티를 모은 것이라고 생각하면 편리하다.

Hadoop YARN 은 클러스터상에서 자원관리와 Job 스케쥴링을 위한 프레임워크다.

그외에 provisioning을 위한 Ambari나 Hadoop Data처리를 빠르게 할 수 있는 Spark, 쿼리형태로 분산처리를 위한 Hive등이 Hadoop 연관 프로젝트로 등록되어 있다.


Hadoop 의 성능

이러한 구조를 바탕으로 놀라운 대용량 처리성능을 보여주고 있다. 2009년에 1TB를 62초에 정렬했다고 한다.. (3800클러스터로) DBMS에서 1TB 정렬조회하면 아마 다운될거다;;

Hadoop 의 단점

굉장히 멋지고 훌륭한 기술이지만 단점도 있다. ScaleOut의 단점은 복잡성이라고 이야기를 하는데, 하둡 역시 복잡하다. EndUser는 MapReduce에 접근하기 어렵고 설령 개발자라 해도 설계/개발에 상당한 시간을 투자해야 한다. 그런데 또 이러한 단점을 극복하기 위해서 MapReduce를 쉽게 할 수 있도록 Pig, Hive가 나타나서 이제는 단점이라고 보기도 어렵다.

또 하나의 단점은 오픈소스기반이다. 발전속도도 빠르고 구성하는 컴포넌트도 다양하다. 이 말은 바꿔보면 하나로 조합하기가 힘들다는 점이다. 각 컴포넌트마다 설정해야할 내용도 많고 컴포넌트간의 호환성도 검토해야 한다. 간신히 검토해서 한 세트를 맞춰놓으면 다음버전이 나온다.-_-;; 0.01 의 마이너 버전 업데이트임에도 불구하고 꽤나 많은 내용이 바뀌기 때문에 따라가기가 매우 버겁다는 점이다.

 

 

'BigData' 카테고리의 다른 글

Flume-Kafka-Elasticsearch 테스트  (0) 2016.03.14
Storm특징 및 Spark와의 차이점  (0) 2014.12.12
CAP 정리  (0) 2014.11.28
NoSQL  (0) 2014.11.28
BigData 정의  (0) 2014.11.28

BigData

최근 BigData가 주목받고 있다. 출현배경에 대해서 다양한 IT용어들이 난무하며 설명하고 있는데 나만의 생각으로 쉬운단어를 사용해서 이해한 바를 정리해보는 게 목표이다.

빅데이터 출현배경

예측하기를 원한다.

과거 IT시스템의 목표는 사람이 하던 일을 보다 정확하고 빠르게 수행할 수 있도록 도와주는 것이었다.물론 CRM 이라는 것이 있었지만 그저 개념이었을 뿐 크게 효과가 있었는지는 의문으로 남아있다. 하지만 최근에는 보다 더 빠른 움직임(고객대응, 상품출시등)을 통해서 경쟁 속에서 살아남기 위한 필수도구로 IT가 지원을 하고 있다. 이를 위해서 사용자 정보, 소비행위 등에 대해서 보다 적극적으로 수집하고 싶어한다.

SNS

전 세계에서 불고있는 SNS열풍이다. 특히 스마트폰의 발전으로 인해서 개인시 컨텐츠를 소비할 뿐만 아니라 적극적으로 생산하는 시대속에서 살고 있다. 이러한 데이터를 처리하기 위해서는 기존의 RDBMS로 한계가 있다.

통신기술의 발전

스마트폰 뿐만 아니라 이제는 사물간 통신이 점차 증가함에 따라서 데이터가 증가하고 있다. 각종 센서데이터를 통해서 수집되는 데이터들이 늘어나고 있다. SNS에서 개인이 컨텐츠를 생산했다면 이제는 온갖사물로부터 데이터가 생성되고 있다.

빅데이터의 3가지특징

Volume

과거에는 Giga단위의 데이터였지만 이제는 Tera, Peta에 이른다

Velocity

배치성 대량 데이터외에도 실시간, 준실시간으로 데량데이터가 발생한다.

Variety

비정형, 반정형의 데이터가 발생한다. 과거에는 정형데이터를 중심으로 모델링을 통해서 데이터를 적재했다면 이제는 비정형,반정형의 데이터를 구조없이 일단 수집한 뒤 나중에 처리하는 방식이 고려되고 있다.

Value

기존3가지의 특징이 있더라도 가공했을 때 비지니스적 가치를 주지 못한다면 빅데이터로 보기 어렵다는 의견도 있다.

빅데이터의 주도권

현재 주목받고 있는 구글, 야후, 페이스북, 아마존등은 모두 기술을 이용한 서비스로 비지니스를 하는 서비스업체로, 이러한 회사들은 다양한 빅데이터를 운영한 경험과 각종 오픈소스를 통해서 기술력을 축적해왔으며 현재 빅데이터에서 주도권을 가지고 있다.

'BigData' 카테고리의 다른 글

Flume-Kafka-Elasticsearch 테스트  (0) 2016.03.14
Storm특징 및 Spark와의 차이점  (0) 2014.12.12
CAP 정리  (0) 2014.11.28
NoSQL  (0) 2014.11.28
Hadoop 이란  (0) 2014.11.28

<개요>

volatile은 컴파일러가 특정변수에 대해서 옵티마이져에 대해서 캐슁을 하지 않고, 리오더링을 하지 않도록 해주는 키워드라고 한다.

그로 인해 멀티쓰레드 환경에서 동기화문제를 만날 때 사용하는 경우가 많다.

 

<내용>

예를 살펴보자

기본적으로 자바기본형은 thread-safe하지만 개발환경에 따라 특이한 경우가 발생할 수 있다.

32bit환경에서 long이나 double처럼 64bit 값을 처리할 때 assign이 두단계에 걸쳐서 일어나게 된다. 

(address의 한계때문에 발생한다.


volatile키워드를 사용할 경우 이에 대한 원자성을 보장하여 오류를 방지해준다.


그렇다면 synchronized 는 언제 사용할까? 위와 같이 volatile로 선언하더라도

public void add(int i){

    longResult += i;

}

와 같은 메소드를 수행하면 + 연산까지 원자성을 보장하지는 않기 때문에 마찬가지로 오류가 발생할 수 있다.


이때 add 메소드에 대해서 synchronized 키워드를 사용하여 동기화를 적용한다.


하지만 해보신분들은 알겠지만 synchronized를 사용하는 순간 엄청나게 느려진다. 어찌보면 당연한 결과이다...

 

<정리>

이를 보완하기 위해서 JDK 1.5이후에서는 Atomic 타입을 제공

Class Description
AtomicBoolean
A boolean value that may be updated atomically.
AtomicInteger
An int value that may be updated atomically.
AtomicIntegerArray
An int array in which elements may be updated atomically.
AtomicIntegerFieldUpdater<T>
A reflection-based utility that enables atomic updates to designated volatile int fields of designated classes.
AtomicLong
A long value that may be updated atomically.
AtomicLongArray
A long array in which elements may be updated atomically.
AtomicLongFieldUpdater<T>
A reflection-based utility that enables atomic updates to designated volatile long fields of designated classes.
AtomicMarkableReference<V>
An AtomicMarkableReference maintains an object reference along with a mark bit, that can be updated atomically.
AtomicReference<V>
An object reference that may be updated atomically.
AtomicReferenceArray<E>
An array of object references in which elements may be updated atomically.
AtomicReferenceFieldUpdater<T,V>
A reflection-based utility that enables atomic updates to designated volatile reference fields of designated classes.
AtomicStampedReference<V>
An AtomicStampedReference maintains an object reference along with an integer "stamp", that can be updated atomically.

public class AtomicLong extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 1927816293512124184L;

    // setup to use Unsafe.compareAndSwapLong for updates
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;

<중략>

private volatile long value;  /**
     * Creates a new AtomicLong with the given initial value.
     *
     * @param initialValue the initial value
     */
    public AtomicLong(long initialValue) {
        value = initialValue;
    }

/**
     * Atomically adds the given value to the current value.
     *
     * @param delta the value to add
     * @return the previous value
     */
    public final long getAndAdd(long delta) {
        return unsafe.getAndAddLong(this, valueOffset, delta);
    }

 a. 예를 들면Long대신에 AtomictLong을 사용하고 제공되는 addAndGet메소드를 사용할 경우 멀티쓰레드 간의 값을 보장하면서 속도도 매우 빨라진다.


 b. 내부적으로 코드를 살펴보면 AtomicLong은 Number를 확장하며 Serializable을 impl한다 (어찌보면 당연하다..)

 c. 멤버변수로 private volatile long value를 가지고 있으며 addAndGet메소드는 final로 선언되어 무한루프를 반복한다.

 d. Unsafe class의 compareAndSwapLong 메소드를 활용한 compareAndSet메소드를 사용한다. 모든 연산메소드가 동일하다.

 

<참고사이트>

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html

불변객체라고 부른다. Java에만 있는 개념은 아니고, 일반적으로 왠만한 언어에는 다 있는 개념이다.

간단히 설명하면 immutable object는 최초에 생성된 뒤 변화할 수 없는 객체이다.

대조적으로 mutable object는 수정이 가능하다.


String s = "ABCDEC";

s.toLowerCase();

toLowerCase는 "ABCDE"를 바꾸는 것이 아니라 "abcde"라는 새로운 String 객체를 생성한다.

(jdk소스를 보면  return new String(result, 0, len + resultOffset); 와 같이 되어있다.)


유사한 immutable로는 Integer, Long, Short, Double, Float, Character, Byte, Boolean등의 Primitive wrapper가 있다. 이러한 immutable object들은 thread-safe와 보안의 목적으로 자주 사용된다.


인위적으로 불변객체를 만들어서 값의 변경이 불가능하도록 하는 것도 가능하지만 생각보다 귀찮은 방법이다. 

(방어복사 : defensive copying)

간략하게 설명하면 class와 멤버변수를 final로 정의하고, setter메소드를 없앤다.

또한 getter메소드에서 값을 반환할 때 clone을 생성하여 반환하도록 한다.

(만약에 멤버변수가 객체라면 해당객체를 deep copy해야 보다 완벽할 듯)


immutable object에는 많은 장점이 있다.

- 기본적으로 thread safe하고

- 동기화작업에서 이점이 있다. (lock을 걸 필요가 없다.)

- 또한 안정한 공유,재사용이 되기 때문에 cache를 사용하여 성능향상 및 메모리 효율을 도모한다.

- 이러한 공유는 복잡도를 감소시킨다. O(n) => O(1)


다만 대량 작업을 수행할때 몇가지 속도에 단점이 있어서 튜닝이 필요한 부분들이 있었다.

- concatenation연산이 새로운 객체생성으로 인한 비용이 비싼편이다. 물론 1.6이후였나? StringBuilder를 사용하기 떄문에 대부분 해소가 된다.

- 반복적인 new copy의 경우 메모리 소모가 매우 증가한다. 100만번 loop문을 수행하면 @.@


내가 수행하고자 하는 업무의 특성에 따라 맞게 사용하면 될 듯한데, WAS상의 온라인업무에서는 적극 활용되는 모습니다.


참고(http://stackoverflow.com/questions/9544182/why-are-strings-immutable-in-many-programming-languages)


1. 공통점과 차이점 비교

공통점

- 인스턴스화 할 수 없다.

- 상세구현없이 메소드를 정의한다.


차이점

- Interface의 경우 public만 가능하다.

- Interface의 경우 동시에 여러개 사용이 가능하지만, Abstract Class의 경우 하나만 사용가능하다.


2. 적용되는 유형

Abstract Class

- 연관되는 클래스들이 공통되는 코드를 포함하고 있을 때

- public외의 접근자 사용이 필요할 때

Interfaces

- 연관성없는 클래스들이 각기 구현이 필요할 경우

- 상세구현내용에 대해서는 몰라도 될때


3. 정리

- Interface의 경우 제공되는 기능을 중심으로 정리되는 듯 하다. 

  ex) JDBCOperation, ItemOperation

- Abstract의 경우 추상화를 통한 공통변수, 메소드 정리에 사용된다. 

  ex) Graphic Object (Line, Circle, Rectangle)

- Interface와 Abstract 동시사용이 가능하다. 일반적으로 팩토리 패턴에서 많이 사용된다.


인터페이스의 경우 원격호출을 통해서 사용할 때 상대에게 방식을 알려주는 용도로 많이 사용된다.

따라서 한번 정의되면 변경이 쉽지 않기 때문에 처음 정의시 고민이 필요하다.

Abstract의 경우 기본구현을 통해서 뼈대를 만들고 각 상세메소드는 상속클래스에서 정의하는 방식을 많이 사용한다.

이 때 상위클래스의 빈 메소드는 Abstract Method로 정의해주는 것이 혼란을 피할 수 있다.


짧지 않은 IT생활을 하면서 얻었던 소중한 경험중에 하나는 Rebecca Wirfs-Brock에게 6개월간 강의를 들었던 것이다. 온/오프라인에 걸쳐서 업무와 병행하여 수강하는 것이(그것도 영어로 ㅜㅜ) 쉽지는 않았지만... 그 뒤로 Application Design을 보는 눈이 달라졌다고 생각한다.

하나를 만들더라도 재사용이 가능하게, 쉽게 확장이 가능하게

이를 위해서 배웠던, 어쩌면 이미 모두가 알고 있는 Designing Object-Oriented Software 에 대해서 차근차근 정리해보려고 한다.  (벌써 2년이나 지나서 가물가물 @.@)

+ Recent posts