레이블이 NoSQL인 게시물을 표시합니다. 모든 게시물 표시
레이블이 NoSQL인 게시물을 표시합니다. 모든 게시물 표시

RDB vs NoSQL 비교 분석

참고 자료
XML 데이터 형식 메서드 http://technet.microsoft.com/ko-kr/library/ms190798.aspx
MySQL http://www.mysql.com/products/community/
MongoDB http://www.mongodb.org/
Cassandra http://cassandra.apache.org/
CAP 이론 http://blog.nahurst.com/visual-guide-to-nosql-systems
Consistency(일관성) : 모든 노드들은 동시에 같은 데이터를 일관되게 유지해야 함
Availability(유효성) : 모든 노드들은 항상 읽기와 쓰기를 할수 있어야 함
Partition Tolerance(파티션 허용) : 시스템은 물리적인 네트워크 파티션을 넘어서도 잘 동작해야 함


MS-SQL 2005
- 상용 라이센스
- Windows
- SQL Server Management Studio(SSMS) 툴 사용
- ODBC API 지원
- 대중적인 RDB로 Table Row(Record) 기반
- MS-SQL2005 부터 XML 지원
- 컬럼내용에 xml 이 저장
- xml 값을 select, update, delete, modify 가능
- xml 의 element 별로 index 처리 가능
- 장점
 : CAP 이론 중 C와A 충족
 : XML 로 데이터를 표현하면 친숙한 RDB 내에서 현재 대용량처리를 위해 주목받고 NoSQL like 기능을 제공
 : Oracle XML 에 비해 API 가 간단하며 직관적이여서 편리하고, 사용 비용이 좀 더 저렴
- 단점
CAP 이론 중 P 불충족
 : 게임 데이터가 급격하게 늘어날 경우 인해 확장이 어려움
 : MySQL XML 은 아직 성능이 현저하게 떨어지고, XML 기능의 범위 또한 제한적(예로, MySQL 은 ExtractValue() / UpdateXML() 하는데 extractvalue 사용시 XML 의 xpath 를 사용하지 못함)
 : 상용으로 비용 발생
 : 리눅스 지원 안함

MySQL 5.1 (Community Edition)
- GPL 상용(Enterprise), 무료(Community)
- Windows / Linux / Solaris / OS X
- SQLyog 툴 지원
- ODBC / MySQL Client API(C/C++/Java...etc)
- 대중적인 RDB로 Table Row(Record) 기반
- XML set / get api 지원
- 장점
 : CAP 이론 중 C와A 충족
 : 무료버전 사용 가능
 : 대중적인 RDB 환경 제공
 : MS-SQL 에 비해 리눅스환경에서 사용가능
- 단점
 : CAP 이론 중 P 불충족(데이터가 급격하게 늘어날 경우 확정이 어려움)
 : Oracle 이나 MS-SQL 에 비해 XML 에 대한 지원 기능이 떨어짐

MongoDB 2.0.2
- MongoDB : AGPL , 커넥터 드라이버는 Apache 2.0 라이센스
- Windows / Linux / Solaris / OS X
- mongo CLI(Command Line Interface) 툴 가능
- mongodb API(C/C++/Java...etc)
- RDBMS 의 대부분 index 지원
- C++ 로 개발됨
- MapReduce 방식의 분산 병렬 처리
- memory mapped db
 : db 의 모든 내용을 OS virtual memory 로 구성하여 paging 여부에 따라 memory <-> disk
 : 32bit mongodb 는 2^32 = 4,294,967,296(4GigaByte) 실제 2.5GB 정도의 데이터 사용가능
 : 64bit mongodb 는 2^64 = 18,446,744,073,709,551,616(18ExaByte) 데이터 사용가능
- disk fragment 방지를 위해 64MB, 128MB, 256MB, .. 1GB, 2GB 등으로 디스크 공간 할당
- 삭제된 데이터 공간은 자동으로 반환하지 않음
 : 예를 들어 100GB 중 50GB 데이터를 삭제해도 100GB 공간을 차직 하고 있음
 : db.repairDatabse() 를 수행하여 정리해야함
- 문서(Document)
 : 문서는 여러개의 필드,필드값 쌍을 가진 단위로 저장,삭제,수정 할 수 있음, JSON 을 바이너리로 인코딩한 BSON 포맷으로 데이터 크기는 4MiB 로 제한
- 컬렉션(Collection)
 : RDB 의 테이블과 유사 개념으로, 네임스페이스로만 의미가 있음
- 데이터베이스(Database)
 : 컬레션을 관리하는 단위
- 장점
 : CAP 이론 중 C와P 충족(master/slave 로 분산 복제로 싱크되어 slave 에서 master 데이터를 똑같이 읽수 있음, Auto-sharding 기능으로 으로 분할 저장 가능)
 : 다양한 클라이언트 라이브러리(C,C++,C#,Java,Javascript,PHP,Perl,Ruby,Python...)를 제공
 : JSON(내부적으로 document 로 불리며, BSON으로 저장) 프토토콜을 사용
 :XML 비해 통신이나 기타 데이터 처리에 있어 빠름
 : XML 은 DOM tree 나 <> 태그등의 오버헤드로 취급될 수 있음
 : 테이블하나에 아주 많은 문서스타일의 데이터를 사용하는 경우에 좋음(예, Log 기록)
- 단점
 : CAP 이론 중 A 불충족 (master 에만 write 할 수 있어 master 에 부하 증가로 write 가 지연될 수 있고 master 장애 발생시 전체 db 를 사용할 수 없음)
 : 메모리와 매핑되는 데이터파일을 사용한다. (즉 main memory 크기를 넘어서는 데이터는 virtual memory (OS가 관리)를 증가시킨다.)
 : 데이터가 머신의 메인 메모리 보다 클 수록 가상메모리를 증가시켜 성능 저하가 발생한다.
큰 데이터를 Insert, Delete 시 성능 저하

Cassandra 1.0.7
- Apache 2.0 라이센스
- Windows / Linux / Solaris / OS X /  기타 JVM 환경
- cassandra-CLI, nodetool 등 제공
- cassandra thrift API(C/C++/Java...etc)
- 구글 bigtable 과 아마존 Dynamo 특징을 토대로 Java 로 개발됨
- Read replica count, write replica count를 설정하여 Availability(유효성)과 Consistency(일관성) 사이의 균형을 사용자가 선택해 사용
 : Write 과정
  1. commitlog -> memtable(memory) -> 일정 threadhold 를 넘어서면 SSTable 로 flush -> SSTable(Disk, 구글의 BigTable 컨셉)
  2. Compaction : SSTable 데이터(key, colunms)를 머지하여 새로운 정렬된 데이터 및 새 인덱스를 생성하는 작업
- Rowkey(1차인덱스), Column(2차인덱스) 을 기본적으로 인덱싱
- 클러스터(Cluster)
 : 여러대의 서버로 구성된 카산드라 클러스터 자체
- 키스페이스(KeySpace)
 : RDB 의 스키마에 해당하는 개념으로 하나의 카산드라 클러스터는 여러개의 키 스페이스를 가질 수 있음
- 칼럼패밀리(ColumnFamily)
 : RDB 의 테이블에 대응하는 개념으로 키 스페이스는 여러개의 칼럼 패밀리를 가질 수 있음
칼럼(Column) : 카산드라에서 저장되는 데이터의 최소 단위이며, 이름, 값, 타임스탬프를 가짐(이름이 키역할을 함)
- 슈퍼칼럼(SuperColumn)
 : 여러 개의 칼럼을 묶어 관리하는 단위이며, 칼럼 패밀리 정의 시 ColumnType=Super 로 명시해야함
- 장점
 : 머지로 인해 여유 공간을 만들어냄
 : disk io 탐색을 줄일 수 있음
 : CAP 이론 중 A와P 충족
 : 현재까지 기존의 RDB 를 대체하는데 가장 적합하여 사용하는 곳이 많음
 : RDB 에 비해 유동적인 데이터 크기를 가져 효율적(Compaction 기능)
 : SSTable(Sorted String Table)에 데이터를 추가후 SSTable 단위로 저장하기 때문에 Write 빠름
 : Column 을 모아 저장하는 Column oriented DB 라서 연관된 데이터를 읽기에 적합
 : 장비추가의 과정이 단순 (새로운 장비를 추가하고 설정을 바꾼 후 cassandra 재시작)
- 단점
 : SuperColumn 안의 컬럼은 인덱스 지원 안됨
 : CAP 이론 중 C 불충족 (성능을 높이면 Consistency 가 낮아짐)
 : thrift 와 같은 rpc frame work 를 사용해서 클라이언트 개발
 : 조금 생소한 컬럼베이스
 : Java 로 만들어져 JVM 이 설치되어 있어야함

Cassandra 설치 및 쿼리

# 구글의 Bigtable과 아마존 Dynamo 의 특징을 합쳐서 만듦
# 장비추가의 과정이 단순(새로운 장비를 추가하고 설정을 바꾼 후 cassandra 재시작)
# 어떤 노드에 장애가 발생하더라도 전체 시스템이 멈추지 않음
# Availability(유효성)과 Consistency(일관성) 사이의 균형을 사용자가 선택해 사용(Read replica count, write replica count를 설정하여)
# Column 을 모아 저장하는 Column oriented DB 라사 연관된 데이터를 읽기에 적합
# SSTable(Sorted String Table)에 데이터를 추가후 SSTable 통째로 저장하기 때문에 데이터를 넣을 위치를 찾을 필요가 없어 Write 가 빠름
# 사용방법 : CLI(Command Line Interface) 쉘을 이용하거나 카산드라 쓰리프트(interface/thrift)를 이용한 프로그램 개발
# 데이터모델
# 클러스터(Cluster) : 여러대의 서버로 구성된 카산드라 클러스터 자체
# 키스페이스(KeySpace) : RDB 의 스키마에 해당하는 개념으로 하나의 카산드라 클러스터는 여러개의 키 스페이스를 가질 수 있음
# 칼럼패밀리(ColumnFamily) : RDB 의 테이블에 대응하는 개념으로 키 스페이스는 여러개의 칼럼 패밀리를 가질 수 있음
# 칼럼(Column) : 카산드라에서 저장되는 데이터의 최소 단위이며, 이름, 값, 타임스탬프를 가짐(이름이 키역할을 함)
# 슈퍼칼럼(SuperColumn) : 여러 개의 칼럼을 묶어 관리하는 단위이며, 칼럼 패밀리 정의 시 ColumnType=Super 로 명시해야함

# 다운로드
wget http://mirror.apache-kr.org/cassandra/1.2.5/apache-cassandra-1.2.5-bin.tar.gz
tar zxvf apache-cassandra-1.2.5-bin.tar.gz
cd apache-cassandra-1.2.5

# 설정 수정
vi conf/cassandra.yaml
data_file_directories:
    - /home/ysoftman/apache-cassandra-1.2.5/ysoftman_db/data
commitlog_directory: /home/ysoftman/apache-cassandra-1.2.5/ysoftman_db/commitlog
saved_caches_directory: /home/ysoftman/apache-cassandra-1.2.5/ysoftman_db/saved_caches

vi conf/log4j-server.properties
log4j.appender.R.File=/home/ysoftman/apache-cassandra-1.2.5/ysoftman_db/log/system.log

# Cassandra 구성 하기
# JDK 설치(http://www.oracle.com/technetwork/java/javase/downloads/index.html)

# 다음 처럼 set
set CASSANDRA_HOME=/home/ysoftman/apache-cassandra-1.2.5

# Cassandra node tool
# 디스크 강제 쓰기
bin/nodetool -h localhost flush

# 요청 작업 상태 보기
bin/nodetool -h localhost tpstats

# thrift 상태 보기
bin/nodetool -h localhost statusthrift

# cfg 상태 보기(db 크기등..)
bin/nodetool -h localhost cfstats

#Cassandra 실행
bin/cassandra -f > null &

# Cassandra 쿼리하기
# Cassandra-cli (Command Line Interface) 실행하고 접속하기(포트 30000 사용)
bin/cassandra-cli
connect localhost/30000;

# 또는 한번에 시작하면서 접속하기
bin/cassandra-cli --host localhost --port 30000

# 클러스터 목록 보기
show cluster name;

# 키스페이스 목록 보기
show keyspaces;

# 키스페이스 생성
create keyspace testdb;

# 키스페이스 제거
drop keyspace testdb;

# 키스페이스 선택
use testdb;

# 컬럼패밀리(cf) 생성
create column family col1 with comparator=UTF8Type and subcomparator=UTF8Type and column_type=Super and key_validation_class=UTF8Type and default_validation_class=UTF8Type;

# cf 의 rows_cache 크기 변경
update column family col1 with rows_cached=5000;

# cf 의 keys_cache 크기 변경
update column family col1 with keys_cached=2000;

# cf 의 secondary index 설정
# rowkey 가 첫번째 인덱스
# super column 에 인덱스 지원 안됨
update column family col1 with column_metadata= [{column_name:temp, validation_class:UTF8Type, index_type:KEYS}];

# cf=col1에 rowkey=1234, super컬럼=Map, MapID_100컬럼=1000 저장
set col1[1234][Map][MapID_100]='1000';

# cf=col1에 rowkey=1234, super컬럼=Map, Score_100컬럽=100 저장
set col1[1234][Map][Socre_100]=100;

# cf=col1에 rowkey=1234, 모든 컬럼 조회
get col1[1234];

# cf=col1에 rowkey=1234, 컬럼 10개 까지만 조회
get col1[1234] limit 10;

# cf=col1에 rowkey=1234, Map의 Score_100 컬럼 삭제
del col1[1234][Map][Score_100];

# cf=col1에 rowkey=1234, 데이터의 모든 컬럼 삭제
del col1[1234];

# cf col1 모든 데이터 1000 개까지 조회
list col1 limit 1000

# cf=col1에 rowkey=1234, 컬럼 개수
count col1[1234];

MongoDB server and command

# ysoftman
# C++ 로 개발된 확장가능하고, 고성능의 document-oriented DB
# MongoDB 자체는 오픈소스(GNU AGPL)이며 사업적 지원은 10gen이라는 회사를 통해 받을 수 있음
# MongoDB Driver 는 Apache 2.0
# RDBMS 의 대부분 index 지원
# 새로운 서버를 쉽게 추가하며, 자동 복구 기능
# Hadoop 의 MapReduce 같은 분산 병렬 처리 가능
# Windows, Linux, OS-X, Solaris 지원
# C, C++, Java, C#, Perl, Python, Ruby 지원
# 사용방법 : CLI(Command Line Interface) 쉘을 이용하거나 프로그램에서 API 를 이용하는 방법 제공
# 데이터모델
# 문서(Document) : 문서는 여러개의 필드,필드값 쌍을 가진 단위로 저장,삭제,수정 할 수 있음
# JSON 을 바이너리로 인코딩한 BSON 포맷으로 데이터 크기는 4MiB 로 제한
# 컬렉션(Collection) : RDB 의 테이블과 유사 개념으로, 네임스페이스로만 의미가 있음
# 데이터베이스(Database) : 컬레션을 관리하는 단위

# MongoDB 구성 하기
# 구성도 http://www.mongodb.org/display/DOCSKR/Introduction
# client(application) 은 router Server 에 접속해서 쿼리를 요청하면 된다.
# client 가 write 요청을 했다면 router 는 master mongodb 로, read 했다면 slave mongodb 로 안내한다.
# mongodb 서버에 1000을 더한 포트로 접속하면 MongoDB 모니터링 웹을 볼 수 있다.(http://127.0.0.1:56555)

# mkdir ysoftman_db_master
# mkdir ysoftman_db_slave
# mkdir ysoftman_db_config

# .lock 파일 삭제
rm -rfv ./ysoftman_db_master/*.lock
rm -rfv ./ysoftman_db_slave/*.lock
rm -rfv ./ysoftman_db_config/*.lock

# master mongoDB Server 시작하기
bin/mongod --master --dbpath ./ysoftman_db_master --port 10010 > /dev/null &

# slave mongoDB Server 시작하기(master 와 다른 장비에서)
#bin/mongod --slave --dbpath ./ysoftman_db_slave --port 10020 --source 10.10.10.100:10010 --autoresync > /dev/null &

# config mongoDB Server 시작하기
bin/mongod --dbpath ./ysoftman_db_config --port 10001 > /dev/null &

# router Server 시작하기
bin/mongos --port 10000 --configdb 10.10.10.100:10001 > /dev/null &

# router Server 접속해서 Sharding 하기
bin/mongo 10.10.10.100:10000

# 참고로 mac 에서 mongo cli 설치 후
brew tap mongodb/brew
brew install mongodb-community-shell

# 원격 접속하기
mongo "mongomongodb://root:ysoftman@10.10.10.10.200:9300/admin?connectTimeoutMS=10000&authSource=admin&authMechanism=SCRAM-SHA-1"

# SQL to mongo mapping chart
# http://www.mongodb.org/display/DOCS/SQL+to+Mongo+Mapping+Chart

# MySQL term   Mongo term
# database database
# table collection
# index index
# row BSON document
# 하나의 document 최대 크기 16MB

# admin db 를 사용해서 설정해야 한다.
use admin;

# shard 추가하기, router 랑 같은 머신의 shard 를 사용할 수 있도록 옵션 명시
# 실제 사용시에는 router 랑 다른 머신의 shard 를 사용해야 한다.
db.runCommand({addshard:"10.10.10.100:10010", allowLocal:true});

# database 단위에서 sharding enable 하기
db.runCommand({enablesharding:"testdb"});

# col1 collection 의 _id 별로 자동 분산되어 저장하도록 하기
db.runCommand({shardcollection:"testdb.col1", key:{"_id":1}});

# sharding 상태확인
db.printShardingStatus();

# shard 삭제하기
db.runCommand({removeshard:"10.10.10.100:10010"});

# testdb 사용하기(DB 를 미리 생성하지 않는다.)
use testdb

# routerinfo 콜렉션 생성
db.createCollection("routerinfo");

# 예) JSON 형식으로 정보 추가
db.routerinfo.save(
{
  "id": "1234",
  "name": "ysoftman",
  "timestamp": 12345,
  "userkey": "UserNo",
  "metainfo": {
    "list": [
      { "name": "UserNo", "desc": "사용자", "type": "int" },
      {
        "name": "Item",
        "desc": "아이템",
        "list": [
          { "name": "a", "desc": "아이템1" },
          { "name": "b", "desc": "아이템2" }
        ]
      },
      { "name": "phone", "desc": "전화번호", "type": "int" },
      { "name": "name", "desc": "이름" },
      { "name": "trash", "desc": "쓰레기" },
      {
        "name": "Map",
        "desc": "맵",
        "pk": "MapID",
        "array": [
          { "name": "MapID", "desc": "맵번호", "type": "int" },
          { "name": "MinScore", "desc": "최소점수", "type": "int" },
          { "name": "MaxScore", "desc": "최대점수", "type": "int" }
        ]
      }
    ]
  }
}
);


#####


# mongo cli 예시
# 도움말
help()

# Database 목록보기
show dbs

# testdb 사용하기(DB 를 미리 생성하지 않는다.)
use testdb

# 현재 사용중인 DB 확인
db.getName()

# 현재 Databse 컬렉션 보기
show collections

# 크기 제한 설정하여 컬레션 생성 size: 크기, max: 최대 개수
#db.createCollection("col1", {capped:true, size:100000, max: 1000});
db.createCollection("col1");

# 컬렉션 이름이 숫자로 시작하거너 - 이 있으면
db["1234"] 또는 db.getCollection("aaa-bbbb")
# 위 해당 사항이 아니라면 다음과같 간단히도 사용할 수 있다. 
db.col1

# 컬렉션 상태 보기
db.col1.validate()

# col1 켈렉션 자체 삭제하기
db.col1.drop()

# col1 컬렉션 모든 document 삭제
db.col1.remove({})

# col1 컬렉션에스 쿼리에 해당하는 document 만 삭제
db.col1.remove({_id:"123"})

# col1 라는 컬렉션에 Name, URL, LastUpdate 등의 데이터를 저장하기(insert() or save())
db.col1.save({UserNo:0, Map:[{MapID:1, Score:100}, {MapID:2, Score:200}]});

# col1 의 다큐먼트 개수 파악하기
db.col1.count()

# col1 의 모든 다큐먼트 검색하기
db.col1.find()

# col1 의 모든 다큐먼트 검색하기(들여쓰기하여 출력)
db.col1.find().pretty()

# UserNo 가 555 인 다큐먼트 찾기
db.col1.find({UserNo:555})

# UserNo 가 555 인 다큐먼트를 찾아서 Map.MapID 필드만 보여주기
db.col1.find({"UserNo":555}, {"Map.MapID":1});

# UserNo 가 555 인 다큐먼트를 찾아서 _id 는 제외하고 Map.MapID 필드만 보여주기
db.col1.find({"UserNo":555}, {_id:0, "Map.MapID":1});

# col1 의 모든 다큐먼트 검색하기(_id 로 오름차순 정렬로 보여주기 -1이면 내림차순)
db.col1.find().sort({_id:1})

# Map.MapID 의 값이 10 인 다큐먼트 개수
db.col1.find({"Map.MapID":10}).count()

# Map.MapID 의 값이 100 보다 큰거나 같은 다큐먼트 개수
db.col1.find({"Map.MapID":{$gte:100}}).count()

# UserNo 가 555 이고 Map 배열의 첫번째 MapID 값을 1234 로 변경하기(조건에 해당하는 내용이 없으면 다큐먼트 하나가 추가된다)
db.col1.update({"UserNo":555}, {$set:{"Map.0.MapID":1234}}, true);

# UserNo 가 555 이고 Map 배열의 100번째 MapID 값을 삭제하기
db.col1.update({"UserNo":555}, {$unset:{"Map.100.MapID":1}});

# UserNo 가 555 이고 Map 배열중 MapID 가 2인 곳을 찾아내어 123 값으로 설정한다.
db.col1.update({UserNo:555, "Map.MapID":2}, {$set:{"Map.$.MapID":123}})

# UserNo 가 555 이고 Map 배열에 object 추가(array 필드에 대해서만 사용할 수 있다)
db.col1.update({UserNo:555}, {$push:{Map:{"MapID":333, "MinScore":300, "MaxScore":500}}})

# 현재 컬렉션의 데이터 하나 삭제하기(검색 결과 id로 지운다)
db.col1.remove({_id:ObjectId("4d5a1ad2e812000000000515")})

# 현재 컬렉션의 모든 document 삭제
db.col1.remove({})

# 인덱스 생성(1:ascending, -1:descending)
db.col1.ensureIndex({"UserNo":1});

# 현재 인덱스 확인(db.system.indexes.find() 전체 인덱스 확인)
db.col1.getIndexes()

# 인덱스 삭제
db.col1.dropIndexes()

# db 상태 확인(data, index 사이즈 등...)
db.stats();

# 서버 상태 확인
db.serverStatus()
db.serverStatus().mem
db.serverStatus().extra_info

# 클라이언트 종료
exit

MongoDB 알아두기

# ysoftman
# 참고 자료
# http://www.mongodb.org/display/DOCS/Replication
# http://en.wikipedia.org/wiki/MongoDB
# http://docs.mongodb.org/manual/faq/developers/#when-does-mongodb-write-updates-to-disk

# Memory Mapped File 이란
# 가상메모리의 한부분으로 파일을 메모리에 매핑하여 사용함
# 따라서 메모리에 맵핑된 파일은 메모리처럼 다룬다.
# MongoDB 에서는 가상메모리 관리를 전적으로 OS 에 의존

# Write 발생시
# 메모리에 먼저 write 후 백그라운드 쓰레드로 1분 주기로 Disk 기록(write back)
# disk 기록 실패 발생시 데이터 유실로 인해 일관성이 깨질 수 있음

# Read 발생시
# 메모리에 로딩해 놓은 상태에서 read 수행

# Mongodb 속도는 인덱스 사이즈와 메모리에 좌우
# 메모리가 가득차서 가상메모리리를 사용할 경우, 데이터 처리속도 급감

# 서버 역할
# master server : 읽기, 쓰기로 사용
# slave server : 읽기로만 사용, master 복제(백업)하고 있음
# arbiter server : master, slave 체크하고, 장애 발생시 slave 하나를 master 로 선정

# 기본적으로 master 만 write 를 수행하기 때문에 master 에 write 부하가 생김
# 이를 해결하기 위해서 데이터를 분산저장하는 auto-sharding 을 이용

# 2가지 Replication 방법 제공
# master-slave
# master 1대에 n대의 slave 가 붙어서 복제한다.
# slave 는 master 의 데이터를 카피하고 읽기전용이나 백업용도로만 사용한다.(not writes)
               
# replica-set
# mongodb 1.6 이후부터 지원되기 시작했다.
# master-slave 구조에 arbiter(master, slave 의 heartbeat 를 체크하여 master 장애 발생시 자체적으로 slave 중 하나를 master 를 선정) 노드를 추가하여 fail-over 지원

Zookeeper 사용하기

# Zookeeper 에 대해서... by ysoftman
# 분산환경의 정점에서 환경 전체를 관리하는 역활, Hadoop 의 서브 프로젝트로 시작, 야후의 분산 코디네이터로 사용
# 참고로 Apache 분산처리 프로젝트는 동물이름이 많음, Hadoop(코끼리), Pig(돼지), Chukwa(거북이)...Zookeeper(동물사육사)라는 이름에서도 알듯이 여러 분산처리 시스템을 관리해주는 것을 뜻함
# 부하 분산 : 하나의 서버만 처리하지 않고, 여러 서버에 분산하여 동시에 작업하도록 지원
# 분산락 해결 : 하나의 서버에서 처리된 결과가 또다른 서버들과 동기화하여 데이터 안정성 보장
# 장애 판단 및 복구 : 실서버(액티브 서버)에 장애가 발생하면 대기중인 서버(스탠바이 서버)가 실서버로 바뀌어서 일 처리
# 환경설정 관리 : 각각의 다른 서버들의 환경 설정을 주키퍼 하나로 관리
# 일반적으로 주키퍼에 저장하는 데이터는 일반 파일이 아닌 시스템 관리, 모니터링, 락등의 필요한 메타 정보만 저장
# 다중의 서버 집합을 묶어서 관리하는 시스템으로, 여러 서버중 리더가 되는 서버 하나가 존재하며, 모든 서버의 중심이 됨
# 하나의 서버에서 데이터가 변경되면 모든 서버에 전달되어 동기화 됨
# SPOF(Single Point Of Failure) 처리 : 한개의 서버에서 장애가 발생되면 처리한다는 뜻
# 예) 서비스 중인 액티브 서버에 장애가 발생되면 장동으로 스탠바이 서버를 액티브 서버로 전환하여 서비스 처리
# 데이터 모델
# 파일 시스템의 폴더와 파일 구조르와 비슷한 트리 구조로 데이터 저장
# 예) /app1 : 폴더 , /app1/p1 : 데이터가 저장되는 노드로 znode 라고 함
# znode 의 데이터는 메모리에 저장되며, 주키퍼의 힙 메모리 크기 만틈 저장 가능
# 메모리에 저장해서 속도가 빠르지만 데이터 영속성을 위해 트랜젝션 로그와 스냅샷 파일은 로컬 디스크에 저장하여 주키퍼가 재시작하더라도 데이터 유지

# 성능
# 주키퍼는 매우 빠른 속도로 동작
# 하지만 서버 수가 늘어나면 성능 저하

# 설치
# jdk 설치 후 java path 등의 기본적인 설정
# 주키퍼 다운로드 http://apache.tt.co.kr/hadoop/zookeeper/zookeeper-3.3.2/zookeeper-3.3.2.tar.gz

# 예제
# 다운 후 압축 풀고 주키퍼의 설정 폴더(./Zookeeper-3.3.2/conf 로 이동하여 zoo_sample.cfg 을 복사해서 zoo.cfg 파일 생성
zookeeper-3.3.2/conf/cp zoo_sample.cfg zoo.cfg

# zoo.cfg 아래와 같이 되어있음
zookeeper-3.3.2/conf/vi zoo.cfg

# 주키퍼가 사용하는 세션 타임 아웃
tickTime=2000
initLimit=10

# 스냅샷, 로그가 저장될 로컬 디스크 경로
dataDir=/home/ysoftman/data

# 주키퍼가 사용할 포트
clientPort=2181

# 머신이 3대가 있다면 각 머신에 주키퍼를 설치하고 다음과 같이 zoo.cfg 에 다음과 같이 추가
# server.서버아이디=서버IP:일반통신포트:리더선출용포트
# 과반수 선택을 위해 최소 3개 이상의 서버를 설정해야 한다.
server.1=10.10.10.123:2222:3333
server.2=10.10.10.124:2222:3333
server.3=10.10.10.125:2222:3333

# 각 머신마다 dataDIr 에 myid 파일을 작성하고 서버아디를 기록해둔다
# 머신1
cat > /home/ysoftman/data/myid
1

# 머신2
cat > /home/ysoftman/data/myid
2

# 머신3
cat > /home/ysoftman/data/myid
3

# 참고로 머신이 1대 밖에 없다면 주키퍼 서버(인스턴스)를 3개를 띄우자.
# zookeeper1 ~ 3 개의 디렉토리로 압축풀고 각각 zook.cfg 생성한다.
# 각각의 zook.cfg 의 clientPort, dataDir 를 별개로 정하고 각 dataDir 에 myid 를 설정한다.

# 주키퍼 시작
zookeeper-3.3.2/bin/zkServer.sh start (루트권한으로)

# 클라이언트로 접속
zookeeper-3.3.2/bin/zkCli.sh

# help 명령으로 다양한 설명을 볼 수 있다.
[zk: localhost:2181(CONNECTED) 0]help

# 주키퍼 서버 정보 파악해 보기
[zk: localhost:2181(CONNECTED) 1]get /zookeeper

# 주키퍼 루트 디렉토리 확인
[zk: localhost:2181(CONNECTED) 2]ls /

# 주키퍼 ysoftman_data 노드를 생성하고 ysoftman_data 데이터 주기
# 생성하면 나머지 서버들로 싱크된다.
[zk: localhost:2181(CONNECTED) 3]create /zk_ysoftman_node ysoftman_data

# 생성된 노드안의 데이터와 데이터 및 세부 정보 확인하기
[zk: localhost:2181(CONNECTED) 4]get /zk_ysoftman_node

# 생성한 노드 삭제하기
# 삭제하면 나머지 서버들로 싱크된다.
[zk: localhost:2181(CONNECTED) 5]delete /zk_ysoftman_node

# 주키퍼 끝내기
[zk: localhost:2181(CONNECTED) 6]quit

# 위 예제에서 설명한 기능(서버를 등록하고 znode 활용하여 등록/삭게)이 전부
# 락, 서버분산 기능 직접적으로 지원 안함, 그런 기능을 구현하도록 일부 기능 제공받아 개발자가 락, 서버 구현

NoSQL 관련

[CAP 이론]
- 데이터 베이스 CAP 이론(Brewer's CAP) : 데이터 베이스는 C,A,P 중 2가지만 보장할 수 있고, 3개 모두를 보장하는 것을 불가능
  Consistency(일관성) : 모든 노드들은 동시에 같은 노드를 보아야 함
  Availability(유효성) : 모든 노드들은 항상 읽기와 쓰기를 할수 있어야 함
  Partition Tolerance(파티션 허용) : 시스템은 물리적인 네트워크 파티션을 넘어서도 잘 동작해야 함
- CAP 이론을 Nathan Hurst 가 만든 Visual Guide to NoSQL System 그림으로 설명(http://blog.nahurst.com/visual-guide-to-nosql-systems)

[NoSQL(Not only SQL)]
- 기존 관계형데이터베이스(RDB) 와 구분되는 다른 형태의 데이터베이스를 통칭
- 수평적 확장(서버를 하나씩 붙여 나가면서 데이터베이스를 확장)이 용이하려면 P 특성이 필요
- 다양한 데이터와 많은 데이터량을 처리하기 위해 RDBMS 가 갖기 못한 P 의 특성이 필요하면서 등장

[특징]
- 고정된 테이블 스키마 없음
- 일반적으로 수평적 확장 지원
- RDB 에 비해 읽기/쓰기 성능이 좋음

[저장 형식]
- column oriented db
전통적인 RDB 의 경우 테이블을 row(튜플)로 집어넣는 것에 반해, column db column(attribute) 단위로 데이터를 집어넣는다.
비슷한 column 을 압축할 경우 압출률이 좋다.
로그분석과 같이 데이터를 가져오는 것이 목적이아닌 경우 효율적이다.
예) 아래와 같은 테이블이 있을 경우
 ID name sex phone
 1  bill  m  123
 2  steve m  456
row oriented db 는 1, bill, m, 123; 2, steve, m, 456; 으로 row 단위로 읽어온다.
column oriented db 는 1, 2; bill, steve; m, m; 123, 456; 으로 column 단위로 읽어온다.

- document oriented db
JSON 과 같이 일정한 포맷을 그대로 DB 집어 넣는다.
DML(select, insert, update, delete)가 없다. DML 대신 각 언어별로 api 를 제공
예) { "name" : "yoonbyounghoon", "sex" : "male", "phone" : "123-456-789" } 의 경우
RDB 테이블을 사용하면 name, sex, phone 의 attribute 를 만들어야 하지만 document oriented db 는 통채로 집어넣는다.

[주요 NoSQL]
- Cassandra
라이센스 : Apache
개발언어 : Java
프로토콜 : custom, binary
특징 : column oriented
사용예 : FaceBook

- CouchDB, CouchBase(CouchDB + memcached)
라이센스 : Apache
개발언어 : Erlang
프로토콜 : HTTP, REST
통신 포맷 : JSON
특징 : document oriented
사용예 : CRM

- MongoDB
라이센스 : MongoDB 는 AGPL, MongoDB Driver 는 Apache 2.0
개발언어 : C++
프로토콜 : JSON, custom, binary
특징 : document oriented, Hadoop 을 사용할 경우 MapReduce 사용 가능
사용예 : 10gen

- HBase
라이센스 : Apache
개발언어 : Java
프로토콜 : HTTP, REST
특징 : column oriented, Hadoop 기반의 MapReduce 사용
사용예 : FaceBook 메세징 데이터 베이스

MemCached 사용하기

# 여러개의 서버에서 이전에 계산된 값을 메모리에 저장하여 매번 계산하지 않게하는 원격 분산 캐시 시스템
# 주로 데이터 베이스의 부하를 줄이기 위해 사용
# LiveJournal, Wikipedia, Flickr, Twitter, Youtube 등에서 사용
# 내부 구성
# libevent(network library) : 코어부분으로 프로토콜 처리
# 해시테이블 : 요청 유형에 따라 데이터 처리(키-값 쌍으로 기록)하고 통계 정보 기록
# Memcached 클라이언트 라이브러리
# Memcached 서버가 아닌 클라이언트 라이브러리에서 분산 처리 담당
# Memcached 클라이언트 라이브러리의 옵션으로 분산 구성을 설정하면 클라이언트 라이브러리에서 데이터를 여러대의 원격 Memcached 서버로 분배
# Memcached 클라이언트 라이브러리 : libmemcached(C/C++), spymemcached(Java) 2.5 이상
# libmemcahed, spymemcached 등을 이용하여 분산 처리 가능
# memcached 와 libmemcached 를 묶어 MemBase 솔루션 제공

# 설치
# 먼저 libevent 설치
wget http://www.monkey.org/~provos/libevent-1.4.13-stable.tar.gz
tar zxvf libevent-1.4.13-stable.tar.gz
cd libevent-1.4.13-stable
./configure
make && make install
ls -ahl /usr/local/lib/libevent

# memcached
wget https://memcached.org/files/memcached-1.5.14.tar.gz
tar zxvf memcached-1.5.14.tar.gz
cd memcached-1.5.14
./configure --with-libevent=/usr/local/lib/libevent --enable-64bit
make && make install
ls -ahl /usr/local/bin/memcached

# memcached 가 실행 안되면 다음 동적라이브러리 설정파일에 libevent 경로 명시
vi /etc/ld.so.conf.d/libevent-i386.conf
/usr/local/lib/

# 분산 환경을 구축하기 위해서 memcached 클라이언트 라이브러리 사용
# libmemcached
wget http://launchpad.net/libmemcached/1.0/0.44/+download/libmemcached-0.44.tar.gz
# spymemcached
wget http://spymemcached.googlecode.com/files/memcached-2.5-23-g9d5d462-sources.zip

# 예제
# memcached 서버 가동
# 포트 : 11211(디폴트), 메모리(MB단위) : 2GiB, 쓰레드 : 6개, 최대 동시 접속 1024개, 데몬으로 수행(옵션없으면 일반 프로세스로 수행)
memcached -p 11211 -m 2048 -c 1024 -t 6 -d

# telnet 으로 memcached 에 접속해서 상태 확인
# 종료는 ctrl+] 입력후 quit
telnet localhost 11211
Connected to ysoftman-memcache
Escape character is '^]'.
stats

# telnet 이용해서 데이터 저장 및 조회
# key : 키 ysoftmankey
# flag : 사용자 플래그 0
# exptime : 만료시간 60초
# bytes : 데이터의 길이 14
# 데이터 길이가 실제 데이터보다 짝으면 에러 발생
# 데이터 길이가 실제 데이터보다 크면 데이터 길이까지 입력(엔터)해야 함
set ysoftmankey 0 60 14 입력후 엔터
YoonByoungHoon
# 조회
# 60초가 지나면 데이터는 사라져 조회되지 않는다.
get ysoftmankey

# 키값을 모르는 경우, active slabs(데이터가 들어있는 공간) 조회
# stats items 로 조회해도 된다.
stats slabs

# 위 결과 slab(item), dump할 데이터 개수
stats cachedump 1 100

# 덤프 결과 예시
# ysoftmankey : 키값
# 1 b: 키에 저장된 값 크기 1byte
# 1350000000 s : 저장시 타임스탬프
ITEM ysoftmankey [1 b; 1350000000 s]

# 참고로 캐시키 조회 ruby script
https://gist.github.com/bkimble/1365005

# nc(netcat) 로 접속 및 명령을 바로 실행할 수도 있다.
# 상태확인
echo -e "stats" | nc localhost 11211

# 저장된 데이터 개수
echo -e "stats items" | nc localhost 11211

# \r\n데이터\r 으로 이스케이프해야 한다.
# 저장
echo -e "set ysoftman1 0 30 8\r\nysoftman\r" | nc localhost 11211

# 조회
echo -e "get ysoftman1\r" | nc localhost 11211

# 전체 삭제
echo -e "flush_all" | nc localhost 11211

# memcached 데몬 종료
killall memcached

# 커맨드 참고
https://github.com/memcached/memcached/wiki/Commands

Linux HDFS(Hadoop Distributed File System) 구성하기 및 Map Reduce 테스트

# ysoftman
# 분산 소프트웨어 플랫폼으로 대량의 데이터를 처리할때 사용
# 비슷한 플랫폼으로 구글의 GFS(분산 파일 시스템), MapReduce(분산 데이터 처리), BigTable(분산 데이터베이스)
# Hadoop 의 기본 아이디어인 MapReduce 개념을 Google 에서 논문으로 처음 소개
# Apache 검색엔진(Lucene & Nutch) 개발자에 의해 Hadoop 개발 시작
# Yahoo 에서 Hadoop 사용, Google 내 검색 처리를 위해서 MapReduce 기법 적용
# 2,000개의 노드들을 클러스터로 구성해 시연, 앞으로 10,000개의 노드들을 클러스터로 운영하는 것을 목표
# 안정적으로 PetaByte 단위의 자료를 저장하고 처리
# 일반 컴퓨터 클러스터 간의 데이터를 분산하고 처리
# 데이터를 분산시켜 데이터가 위치한 노드들을 병렬로 처리
# 자동으로 데이터 복사본을 유지하여 문제 발생시 재배치 수행
# Hadoop 의 구성 요소
# Hadoop Common : Hadoop 을 사용하는 모든 요서에서 공통으로 필요로 하는 요소
# HDFS(Hadoop Distributed File System) : 대량의 데이터를 분산저장하는 파일 시스템
# MapReduce : 대량의 데이터를 분산 처리할 수 있는 프레임워크
# 연관된 프로젝트
# Avro, Chukwa, HBase, Mahout, Pig, ZooKeeper

[Hadoop 설치]
32bit 일때(hadoop-0.19_32bit.tar.gz , jdk-6u10-linux-i586.bin , fuse-2.7.4.tar.gz) 파일을 기준
64bit 일때(hadoop-0.19_64bit.tar.gz , jdk-6u10-linux-x64.bin , fuse-2.7.3.tar.gz) 파일을 기준
1. root 상태에서 hadoop 계정을 만든다.(useradd hadoop, 홈디렉토리는 /home1/hadoop 이 된다.)
2. hadoop-0.19_32bit.tar.gz 압축을 /home1/hadoop 에 푼다.
3. jdk-6u10-linux-i586.bin 실행한다.(실행 안될 경우 chmod +x jdk-6u10-linux-x64.bin)
4. mv jdk1.6.0_10/ /usr/java/ (jdk 를 /usr/java/ 밑으로 옮긴다)
5. hadoop 계정의 .bashrc를 다음과 같이 만든다.

# .bashrc
# User specific aliases and functions
# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi
export JAVA_HOME=/usr/java/jdk1.6.0_10
export PATH=$JAVA_HOME/bin:$PATH

[hdfs 공간 만들기]
# 예) ysoftman 이라는 서버에 hdfs 공간 만들기
# hadoop 으로 로그인
cd ~/hadoop-0.19

# JAVA_HOME 환경변수가 설정되어 있으면 굳이 하지 않아도 된다.
vi conf/hadoop-env.sh
export JAVA_HOME=/usr/java/jdk1.6.0_10

# 최신버전에는 core-site.xml, hdfs-site.xml, mapred-site.xml 로 분할되었다.
vi conf/hadoop-site.xml
<configuration>
<property>
  <name>fs.default.name</name>
  <value>hdfs://ysoftman.com:9000</value>
</property>
<property>
  <name>dfs.name.dir</name>
  <value>/home1/hadoop/filesystem/name</value>
</property>
<property>
  <name>dfs.data.dir</name>
  <value>/data1,/data2</value>
</property>
<property>
  <name>dfs.http.address</name>
  <value>ysoftman.com:50070</value>
  <description>
    The address and the base port where the dfs namenode web ui will listen on.
    If the port is 0 then the server will start on a free port.
  </description>
</property>
<property>
  <name>mapred.job.tracker</name>
  <value>ysoftman.com:9001</value>
</property>
<property>
  <name>mapred.system.dir</name>
  <value>/home1/hadoop/filesystem/mapreduce/system</value>
</property>
<property>
  <name>mapred.local.dir</name>
  <value>/home1/hadoop/filesystem/mapreduce/local</value>
</property>
</configuration>

# HDFS 마스터 서버 명시
conf/master

# HDFS 슬레이브 서버 명시
conf/slaves

# masters 서버와 slaves서버 모두 데이터로 사용될 디렉토리의 권한을 hadoop으로 설정한다.
chown -R hadoop:hadoop /data1
chown -R hadoop:hadoop /data2

# hadoop file system 공간 포맷하기
bin/hadoop namenode -format

# jps 를 실행하여 NameNode SecondaryNameNode DataNode JobTracker TaskTracker 등이 나타나면 정상작동하는 것이다.
jps

# 마스터와 슬레이브 서버들간에 ssh 자동로그인 하도록 설정한다(ysoftman 포스트 참고)
# hdfs 중지하기
bin/stop-all.sh

# hdfs 가동하기(start-dfs.sh 와 start-mapred.sh 가 모두 실행된다.)
bin/start-all.sh

# ysoftman.com 이 10.10.10.1 이라면 다음의 주소로 hadoop cluster 정보를 확인 할 수 있다.
http://10.10.10.1:50070/

# ysoftman.com 이 10.10.10.1 이라면 다음의 주소로 hadoop map/reduce 작업 현황을 확인 할 수 있다.
http://10.10.10.1:50030/

#####



[hdfs 마운트]
# hdfs 공간을 만들었으면 그 hdfs 공간을 현재 시스템에서 마운트하여 사용한다.
# 예) server1 의 /home1/hdfs 에 만들기
# root 로 로그인해서
tar xvf fuse-2.7.4.tar.gz
configure
make && make install

# fuse 장치 권한 변경
chmod 777 /dev/fuse

# /etc/fuse.conf 파일생성해서 내용추가
vi /etc/fuse.conf
user_allow_other

# fuse
/sbin/modprobe fuse

# hdfs 를 마운트해서 사용할 디렉토디를 생성
mkdir /home1/hdfs
chown -R hadoop:nobody /home1/hdfs

# hadoop 권한에서 fuse 마운트 실행
su hadoop

cd /home1/hadoop/hadoop-0.19/src/contrib/fuse-dfs/src/
./fuse_dfs_wrapper.sh dfs://server1.ysoftman.com:9000 /home1/hdfs

# 만약 libjvm.so 파일이 없다고 나오면 아래의 경로를 /etc/ld.so.conf 에 추가하고 /sbin/ldconfig 실행
/usr/java/jdk1.6.0_10/jre/lib/i386/server/ (32bit OS)
/usr/java/jdk1.6.0_10/jre/lib/amd64/server/ (64bit OS)

[hdfs 마운트 후 작업폴더 설정]
# 예) /home1/hdfs 에 마운트 후 ocr 계정 디렉토리만들고 소유권 넘기기
# hadoop 로그인 상태에서마운트 된곳(/home1/hdfs)에서 작업폴더 만들기
mkdir ocr

# 이렇게 되면 소유자는 hadoop.hadoop 상태가 된다.
# 여기서 소유자 ocr 로 바꾸려면 아래와 같이 한다.(현재 hdfs 마운트되어 /home1/hdfs 가 루트디렉토리가 된다.)
~/hadoop-0.19/bin/hadoop fs -chown -R ocr:ocr /ocr

#####


[Map Reduce 테스트]
# MapReduce 예제 : 두개의 파일로 부터 word count
# 입력 파일 작성
cat > ysoftman1.txt
apple banana milk lemon
cat > ysoftman2.txt
lemon cheese apple coffee

# HDFS 로 복사하기(dfs : hdfs 사용, -put : 복사명령)
./bin/hadoop dfs -put ysoftman1.txt input/ysoftman1.txt
./bin/hadoop dfs -put ysoftman2.txt input/ysoftman2.txt

# hadoop 에 포함된 예제 프로그램 word count 실행
./bin/hadoop jar hadoop-0.20.0-dev-examples.jar wordcount input output

# word count 결과 확인(dfs 대신 fs (일반 file system 사용)을 사용해도 됨)
./bin/hadoop dfs -cat output/part-00000
apple   2
banana  1
cheese  1
coffee  1
lemon   2
milk    1

# mapreduce 작업 모든 상태보기
bin/hadoop job -list all

# mapreduce 로 작업중인 작업 강제 종료하기
bin/hadoop job -kill 작업ID