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


Archive»


 
 


import pika
import ast
import pymongo
import datetime
import logging
import time
import sys,traceback,socket,threading
from datetime import datetime
from time import sleep

# configuration
MONGODB_NAME = "terrydb"
HOSTNAME = ':'+socket.gethostname()
QUEUE_NAME = 'hello'
MONGODB_URL= 'mongodb://localhost'
RABBITMQ_URL='localhost'

LOG_FORMAT = ('[%(levelname)s] %(asctime)s %(name)s : %(message)s')
LOGGER = logging.getLogger(__name__)
              
class WorkerThread(threading.Thread):
    def __init__(self,threadID,name,counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
        # init rabbitmq
        # init mongodb

    # make rabbitMQ connection and create channel
    def initRabbitMQ(self):
        self.q_conn = pika.BlockingConnection(pika.ConnectionParameters(host=RABBITMQ_URL))
        self.q_channel =self.q_conn.channel()
        self.q_channel.queue_declare(queue=QUEUE_NAME) # create queue
    
    # make mongo db connection
    def initMongoDB(self):
        self.mongo_conn = pymongo.MongoClient(MONGODB_URL)
        self.mongo_db = self.mongo_conn[MONGODB_NAME]

    def onMessage(self,ch,method,properties,body):
        try:
            LOGGER.info(str(self.name)+" recevied "+body)
            #print str(self.name) + "[x] recevied %r" % (body,)
            json_dict = ast.literal_eval(body) # convert string to dictionary
            ## need to be fixed
            ## specify board name here
            self.writeToMongoDB('MYBOARD',json_dict)
        except ValueError:
            print 'String parsing error'
        except:
            print 'unknown error'
            traceback.print_exc(file=sys.stdout)
    
    def writeToMongoDB(self,boardname,post):
        # get board name
        s = self.mongo_db[boardname]
        # generate uuid for the posting
        post['_id'] = self.genPostId()
        try:
            s.insert(post)
        except:
            LOGGER.error(" mongodb insert fail" + str(sys.exc_info()[0]) )
            traceback.print_exc(file=sys.stdout)

    # generate post unique id with
    # format : YYMM{microsecond from this month 1}:{hostname}
    def genPostId(self):
        time.sleep(0.001) # intentionally sleep to remove key duplication
        dt = datetime.now()
        year = str(dt.year)[-2:]
        mon = dt.month
        if mon < 10 :
            mon = '0'+str(mon)
        else:
            mon = str(mon)
        print dt.second
        print dt.microsecond
        uid = year+mon+ str ( int(dt.day * 24 * 60 * 60 + dt.second) * 1000 + dt.microsecond / 1000.0)
        uid = uid + HOSTNAME
        return uid
                
    def run(self):
        LOGGER.info(str(self.name)+" has been started")
        self.initRabbitMQ()
        self.initMongoDB()
        self.q_channel.basic_consume(self.onMessage,queue=QUEUE_NAME,no_ack=True)
        self.q_channel.start_consuming()
        #while 1:
        # time.sleep(0.01)


         
    #savePostToDB('helloboard',j)
                    

def print_usage():
    print 'usage : python worker_multithread {number of thread}'
    exit()
    
def main(argv):
    if len(argv) <2:
        print_usage()
    if argv[1].isdigit() ==False :
        print_usage()
    max_thread = int(argv[1])
    logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
    
    LOGGER.info('Create '+str(max_thread)+' threads ')

    threadList =[]
    for i in range(max_thread):
        t_name = "WorkerThread-"+str(i)
        t = WorkerThread(i,t_name,i)
        t.start()
        threadList.append(t)
    
if __name__ == '__main__':
    main(sys.argv)


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

mongodb locking

클라우드 컴퓨팅 & NoSQL/MongoDB | 2014.01.02 15:01 | Posted by 조대협

* Single write lock (per database)

* Reader-Writer lock :  allowing concurrent access to multiple threads for reading but restricting access to a single thread for writes (or other changes) to the resource


(from wikipedia) In computer science, a readers-writer or shared-exclusive lock (also known as the multiple readers / single-writer lock[1] or the multi-reader lock,[2] or by typographical variants such as readers/writers lock) is a synchronization primitive that solves one of the readers-writers problems. A readers-writer lock is like a mutex, in that it controls access to a shared resource, allowing concurrent access to multiple threads for reading but restricting access to a single thread for writes (or other changes) to the resource. A common use might be to control access to a data structure in memory that can't be updated atomically and isn't valid (and shouldn't be read by another thread) until the update is complete.


* Yield lock 

 - from version 2.0 if page fault has been occured in mongod (data is not loaded to memory). It yield lock 

 - long running read locks will ield periodically to ensure that write operations have the opportunity to complete. 


* Sharding & Locking : the lock is not shared across the shard. each shard has its own locking

* Replication & Locking

 - Primary to secondary replication is done by batch way. it copies oplog to secondary and run it as a batch. 


참고 : mongodb FAQ/locking

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

Python을 이용한 간단한 mongodb insert 예제


1. easy_install.exe를 이용하여, mongodb python driver인 pymongo를 설치


2. 코드 작성

 connection얻고, db선택하고,collection(여기서는 users테이블) 선택하면되고,

 insert,update등은 기존 mongodb script와 유사함. 에러 처리는 아래와 같이 try,except 사용

import sys

import pymongo

 

connection = pymongo.MongoClient("mongodb://localhost")

db = connection.terrydb

users = db.users

 

doc = {'_id':'myid','firstname':'Terry','lastname':'Cho'}

 

try:

    users.insert(doc)

except:

     print "insert failed",sys.exc_info()[0]

 

 

3. insert 확인


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

MongoDB를 구성할때 보면, 가장 많이 권장 받는 부분 중의 하나가, 메모리량과 디스크 성능이다.

메모리 크기가 아주 sensitive한 요인이 되는데, 어떤 부분이 문제가 되는지 내부 저장 구조를 살펴 봄으로써 이해를 돕고자 한다.


저장 구조

mongodb는 기본적으로 memory mapped file (OS에서 제공되는 mmap을 사용) 을 사용한다. mongodb는 데이타를 write할때, 논리적으로 memory 공간에 write하고, 일정 주기에 따라서, 이 메모리 block들을 주기적으로 disk로 write하는데, 이 디스크 writing 작업은 OS에 의해서 이루어 진다.


OS에 의해서 제공되는 Virtual Memory를 사용하게 되는데, Pysical Memory 양이 작더라도 Virtual Memory는 훨씬 큰 공간을 가질 수 있다. Virtual Memory는 page라는 블럭 단위로 나뉘어 지고, 이 Block들은 Disk의 block에 mapping이되고, 이 block들의 집합이 하나의 데이타 파일이 된다. (아래 그림 참조)




참고 http://www.polyspot.com/en/blog/2012/understanding-mongodb-storage/


메모리에 저장되는 내용

메모리에 저장되는 내용은 실제 데이타 블록과, Index 자체가 저장이 된다. mongodb에서 index를 남용하지 말라는 이야기가 있는데, 이는 index를 생성 및 업데이트 하는 데 자원이 들어갈뿐더러, index가 메모리에 상주하고 있어야 제대로 된 성능을 낼 수 있기 때문이기도 하다.


만약에 Physical Memory에 해당 데이타 블록이 없다면, page fault가 발생하게 되고, disk에서 그 데이타 블록을 loading하게 된다. 물론 그 데이타 블록을 loading하기 위해서는 다른 데이타 블록을 disk에 써야 한다.

즉, page fault가 발생하면, page를 memory와 disk 사이에 switching하는 현상이 일어나기 때문에, disk io가 발생하고, 성능 저하를 유발하게 된다.


즉 메모리 용량을 최대한 크게 해서 이 page fault를 예방하라는 이야기이다.

그러나, page fault가 안 발생할 수 는 없고, (1TB 저장하려고, 메모리를 진짜 1TB를 저장할 수 없는 노릇이니...). page fault를 줄이는 전략으로 접근 하는 것이 옳은 방법인데..


page fault시 disk로 write되는 데이타는 LRU 로직에 의해서 결정이 된다. 그래서, 자주 안쓰는 데이타가 disk로 out되는데, 일반적인 application에서 자주 쓰는 데이타 (최근 데이타)의 비율은 그리 크지 않다. 예를 들어 게시판이나 블로그만을 생각해보더라도, 앞의 1~10 페이지 정도가 많이 보게 되지 뒤의 데이타를 잘 안보게 된다. 


이렇게 자주 억세스 되는 데이타를 Hot Data라고 하는데,이 Hot Data 들이 집중되서 메모리에 올라가도록 key 설계를 하는 것이 핵심이다.

쓸떼 없이 전체 데이타를 scan하는 등의 작업을 하게 되면, 100% page fault가 발생하기 때문에, table scan등이 필요한 시나리오는 별도의 index table(summary table)을 만들어서 사용하는 등의 전략이 필요하다.


note

Physical memory < Virtual Memory (=Physical memory + Swapping) < mmap = total file size < disk size



Do I need to configure swap space?

Always configure systems to have swap space. Without swap, your system may not be reliant in some situations with extreme memory constraints, memory leaks, or multiple programs using the same memory. Think of the swap space as something like a steam release valve that allows the system to release extra pressure without affecting the overall functioning of the system.

Nevertheless, systems running MongoDB do not need swap for routine operation. Database files are memory-mapped and should constitute most of your MongoDB memory use. Therefore, it is unlikely that mongod will ever use any swap space in normal operation. The operating system will release memory from the memory mapped files without needing swap and MongoDB can write data to the data files without needing the swap system.


http://docs.mongodb.org/manual/faq/diagnostics/#faq-memory



저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

초간단 Mongo DB Quick Start Guide

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

 

Mongo DB NoSQL 중에서 가장 널리 사용되는 인기있는 제품이다. 사용과 운영이 다른 시스템에 비해서 매우 쉽고, JSON 기반의 Document를 제공하기 때문에, 데이타 구조에 대한 이해 및 사용이 쉽다. 또한 index search와 같은 feature를 제공하고 있고, 근래에는 Text Search GridFS를 이용한 파일 저장 그리고, 위치 정보 저장 및 쿼리등 다양한 기능을 제공하고 있다.

 

Mongo DB 10gen이라는 회사에서 개발되어서, 현재 오픈소스로와 상용 버전으로 공급되고 있다.

이 글에서는 Mongo DB에 대한 이해를 돕기 위해서 간단한 설치에서 부터, 자바 기반의 프로그래밍 샘플까지 소개하도록 한다.

 

1.설치

1) 다운로드 하기

mongodbhttp://www.mongodb.org/downloads 에서 다운로드 받을 수 있다. 여기서는 Windows 64-bit Production Release 버전을 기준으로 한다.

zip 파일을 다운로드 받은 후에 C:\dev\mongodb-win32-x86_64-2.4.3 디렉토리에 압축을 풀었다.

2) Mongodb 구동

C:\dev\mongodb-win32-x86_64-2.4.3 에서 다음과 같은 명령어를 이용하여 구동한다.

.\bin\mongod --dbpath C:\dev\mongodb-win32-x86_64-2.4.3\data

3) 콘솔 확인

구동후에, http://localhost:28017 을 접속하면 아래와 같이 mongodb의 기본 관리 화면을 접속할 수 있다.



2.간단한 테스팅

인스톨이 끝났으면 간단한 테스트를 해보자, ./bin/mongo.exe를 수행하면 Java Script 기반의 쉘이 수행된다. 이해를 돕기 위해서 하나의 테이블에 Insert , select, delete, update를 수행하는 명령을 SQL 문장과 비교해서 소개한다.

 

Insert

SQL              : insert into users ("name","city") values("terry","seoul")

Mongo DB     : db.users.insert({_id:"terry",city:"seoul"})

 

Select

SQL              : select * from users where id="terry"

Mongo DB     : db.users.find({_id:"terry"})

 

Update

SQL              : update users set city="busan" where _id="terry"

Mongo DB     : db.users.update( {_id:"terry"}, {$set :{ city:"Busan" } } )

 

Delete

SQL              : delete from users where _id="terry"

Mongo DB     : db.users.remove({_id:"terry"})

 

간단하게 나마, mongodb query에 대해서 설명하였다.

조금 더 자세한 쿼리에 대한 설명은 http://docs.mongodb.org/manual/crud/ 를 참고하기 바란다.

 

3. 자바로 간단한 프로그램 작성하기

지금까지 설치와 간단한 쿼리 수행을 해봤다. 그러면 이번에는 다음 단계로 간단한 자바 클라이언트를 구현해보자, RDBMS를 이용하기 위해서 JDBC 드라이버를 사용한다면, mongodb는 전용 드라이버 mongo-java-driver 를 제공한다.

이 예제에서는 별도로 설치하기 보다는 아래와 같이 maven 빌드 스크립트에 dependency를 추가하여, 빌드시에 자동으로 라이브러리가 로딩 되도록 한다.

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

 

  <groupId>mongodb</groupId>

  <artifactId>simplemongo</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <packaging>jar</packaging>

 

  <name>simplemongo</name>

  <url>http://maven.apache.org</url>

 

  <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  </properties>

 

  <dependencies>

        <dependency>

               <groupId>org.mongodb</groupId>

               <artifactId>mongo-java-driver</artifactId>

               <version>2.10.1</version>

        </dependency>

  </dependencies>

    <build>

        <plugins>

               <plugin>

                       <groupId>org.apache.maven.plugins</groupId>

                       <artifactId>maven-compiler-plugin</artifactId>

                       <version>2.3.1</version>

                       <configuration>

                              <source>1.6</source>

                              <target>1.6</target>

                       </configuration>

               </plugin>

                <plugin>

                       <groupId>org.apache.maven.plugins</groupId>

                       <artifactId>maven-eclipse-plugin</artifactId>

                       <configuration>

                              <downloadSources>true</downloadSources>

                              <downloadJavadocs>true</downloadJavadocs>

                       </configuration>

               </plugin>

 

        </plugins>

  </build>

</project>

 

 

다음은 localhost에 있는 mongodb instance에 하나의 document(RDBMS로 치면 row) insert하는 클라이언트 프로그램 예제이다.

package com.terry;

import com.mongodb.BasicDBObject;

import com.mongodb.DB;

import com.mongodb.DBCollection;

import com.mongodb.MongoClient;

import com.mongodb.ServerAddress;

 

public class SimpleMongo {

       

        MongoClient mongoClient = null;

        DB db=null;

       

        public void mongoTest(String ip,int port,String dbname) throws Exception{

              

               mongoClient = new MongoClient(new ServerAddress(ip,port));

               db = mongoClient.getDB(dbname);

              

               DBCollection userTable = db.getCollection("userTable");

               BasicDBObject doc = new BasicDBObject("name", "MongoDB").

                append("type", "database").

                append("count", 1).

                append("info", new BasicDBObject("x", 203).append("y", 102));

 

               userTable.insert(doc);

        }

       

        public static void main(String args[]) throws Exception{

               SimpleMongo testRunner = new SimpleMongo();

               testRunner.mongoTest("localhost", 27017, "testdb");

        }

}

 

간단한 예제이기 때문에 몇가지만 설명을 하면

com.mongodb.DB mySQL DB등과 같이, RDBMSDB의 개념을 표현한다. 그래서 mongoDB에 연결한후에, db getDB를 통해서 연결한다.

mongoDB에서 테이블은 collection이라는 개념으로 존재한다. Table insert를 하기 위해서는 getCollection 메서드를 사용해서 해당 테이블 객체를 가지고 온후, Json Object를 만들어서 Table (Collection) insert를 하면 된다.

 

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
MongoDB 깜빡 잊고 있었다. Read / Write 성능이 빠를 수 밖에 없다는 걸..
Mongo는 Write시에, Memory에 먼저 Write후에, 1분 단위로 Flushing하는 Write Back 방식을 쓴다. 즉 메모리에만 쓰면 되니까는 Write가 무지 빠르다. 반대로 Read시에는 파일의 Index를 메모리에 로딩해놓고 찾는다(memory mapped file). 이러니 성능이 좋을 수 밖에, 단 Flushing전에 Fail이 되면 데이타 유실에 의해서 Consistency 가 깨지는 문제가 발생하고, Configuration 구조상 메모리 사용량이 많으며, 확장성에 제약이 있다.
특히 Write 구조에서는 비동기 식으로 Write를 하기 때문에 Disk 성능에 덜 Sensitive하다. 즉 이 말은 DiskIO성능이 상대적으로 낮은 클라우드에서 더 잘돌아간다는 이야기.

이에 비해서 Cassandra(같은 Dynamo 계열인 Riak도 마찬가지) 는 Write Back이나 Memory Mapped file을 사용하지 않기 때문에 MongoDB에 비해서 성능이 낮을 수 밖에 없다. 더군다나, Write나 Read시 1개 이상의 Node에서 값을 읽거나(R Value) 쓰기 때문에(W Value) Consistency가 mongoDB에 비해서 나으며, 당연히 확장성도 더 높다.

즉 확장성+일관성 vs 성능간의 Trade Off 구조다.
 
한국 내 정도 서비스 할 수준이라면 걍 mongo가 났겠네.. 대규모 서비스라면 Cassandra 고민해봐야 할듯 하고.
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
MongoDB Deployment 아키텍쳐를 간단하게 보면 다음과 같다.
mongos들을 앞단에 쭈욱 늘어놓고, 이는 라우터의 역할을 한다. mongos간의 load balancing은 앞단에 L4등의 로드 밸런서를 사용하고, Cache Hit율등을 높이기 위해서 L4는 Hash 방식등의 Sticky setting을 한다.
뒷단에 mongod를 배치하고, 최소한 3 copy replica 구조로 설정한다.



inter data center에 대한 replication을 설정하고, 이는 DR이나 Back up 용도로 사용한다
inter data center replication은 항상 여러가지 숙제를 주는데, 이 경우 backbone의 속도 차이로 인하여 data의 일관성이 깨질 수 있으니,
1. DR/Back up 용도로만 사용
2. data center간 초고속 백본만 설치
3. data center A에서는 read/write, B에서는 read만 (Query Off Loading 아키텍쳐) 수행하고, 이 경우에는 B 데이타 센터의 data 반영이 늦음을 예상해서 애플리케이션을 설계한다.

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

대충 2시간 정도 MongoDB를 훝어보니

구조
- mongod는 실제 데이타 베이스 핸들링 프로세스로 mysqld와 유사
- 앞단에 mongos 라는 프로세스를 띄워서 클러스터 구성을 하면, mongos가 로드 밸런서 역할을 함

클러스터링을 할경우
- Sharding을 사용하여 데이타를 분산 저장해야 함
- 이 경우 같은 shard내에 mongod를 3 copy로 replication하여 데이타 유실을 방지를 권고한다.
- 고급 문서 대부분 내용이 Shard 구성과 Index 구성이다. 이게 키 포인트인듯
※ 이 과정은 Redundant한 하드웨어 구성으로 인하여 하드웨어 코스트를 올릴 수 있다.

성능 부분에서는
- mongodb는 memory 기반의 index를 사용하여 cassandra나 hbase 에 비하면 높은 read performance를 보장한다.
- 단 메모리가 충분해야 한다는 이야기고 반대로 이야기 하면 비싸고 확장성에 제약이 있다는 이야기다.

용량 부분에서
- 사례 문서를 보니까는 1 node에 3TB 저장 가능한 문서가 있었고
- 궁극적으로 1000 node를 클러스터로 묶을 수 있다고 했다. 즉 peta byte급의 데이타 저장이 가능하다는 것이다. (실제로 가능할지는 모르겠다.)
- 여기에 아울러 12billion record (120억 레코드)
데이타 상으로만 보면 꽤 큰 데이타 저장이 가능한데, 대부분 문서는 중소형에서만 mongodb를 권장하고 있다.

저장 레코드
- GridFS 기반으로 파일을 저장할 수 있다.
- 대용량 파일은 Chunk 단위로 나눠서 저장이 가능하다. (자동으로 나눠줌)

기술지원
- 10gen에서 컨설팅과 Support 서비스 가능
- foursquare 레퍼런스가 있음. (나름 레퍼런스가 있다.)

결론
- 중소형에서만 사용하는 것이 권장됨
- 아키텍쳐 디자인에서는 Sharding과 Index 구성이 관건
- 하드웨어 아키텍쳐 구조에서는 메모리를 충분히 배치할것
- 그리고 결코 싸지 않다. (3 Copy)

구조도 간단하고, Key/Value Store 방식의 NoSQL에 비해서 Query 기능이나 Index와 같이 RDBMS와 같은 고급 기능도 제공한다. 아주 대용량의 시나리오가 없는 한국에서 그래서 다른 까다로운 NoSQL DB에 비해서 인기가 있는 것인지도..

요즘 분산 시스템은
- Proxy, Sharding, Ring Architecture, 3 Copy, Commodity hardware. 이 3개가 대세인듯. 다 똑같아.
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

요즘 대용량 데이타 처리 때문에, NoSQL을 머릿속에만 올려놓고, 근래에나 되서 이래서는 안되겠다 해서 직접 자료를 찾아보고 있습니다.

NoSQL은 Cassandra, HBase, Mongo, Riak등을 후보군으로 뒀는데,

Cassandra는 FaceBook에서 Donation해서 만든 분산 DB로 개인적으로는 가장 신뢰가 가기는 했지만, 국내의 많은 블로그 포스팅등을 읽어보면, 안정성이나 사용성이 떨어진다는 것이다. 즉 제품은 좋은데 야생마처럼 잘 쓰지 못하면 모쓰는 제품이라는 이야기. 일단 후보로 남겨놓고 패스.

HBase는 Hadoop File System (HDFS)를 기반으로 설계되었는데, 검색해보니 생각보다 많이 사용이 안되는 것 같아서 패스
Riak도 신생이라서 패스

결국은 Mongo와 Cassandra에서 고민하게 되었는데,
신생 MongoDB가 얼마전부터 사람들 입에 많이 입에 오르내리고 있다. 검색을 해봐도 많이 나오고
이는 즉 사용이 쉽다는 것을 의미하고 또한 10gen이라는 회사에서 제품에 대한 Ownership을 지고 서포트와 컨설팅 그리고 라이센스를 제공하고 있다. 둘다 오픈소스(?)이긴 하지만 자기네들만이 사용하기 위해 만든 Cassandra와는 태생 자체가 다르다는 사실

요즘 분산 아키텍쳐를 보면 대부분 비슷한것이 앞단에 Load Balancing을 해주는 Proxy 를 두고, 뒤에 데이타 처리를 하는 Processing Node를 두는 것이 일반적인데, SWIFT도 글코, MogileFS도 글코, 분산 처리 환경인 Gearman이나 Hadoop도 결국은 비슷하다. 아니나 다를까, MongoDB도 유사한 구조를 갖는다.

일단 기능적인 특징을 보면

Indexing이 가능하다.
이말은 즉 빠른 Search가 가능하다는 이야기인데, 문서를 찾아보니, Index는 메모리에 저장되기 때문에, 메모리 크기에 영향을 많이 받는다. 즉 Deployment설계할때, 하드웨어의 Memory 사이즈가 중요한 Factor 라는 것

GridFS 기반의 Blob 데이타 저장 지원
GridFS라는 분산 파일 시스템을 사용하여 Binary 데이타 저장이 가능하다. 일반적인 아키텍쳐에서 meta 정보를 DBMS에, binary를 File System에 나눠서 저장할때, 이로 인해서 발생되는 데이타 일관성에 불일치를 방지할 수 있다는 점에서는 혁신적인데.. 문제는...
국내의 어느 블로거가 테스트한 데이타 http://symplog.tistory.com/entry/MongoDB-MongoDB-GridFS-%EB%B6%80%ED%95%98%ED%85%8C%EC%8A%A4%ED%8A%B8 를 보면, 파일 업로드 다운로드 성능이 그리 뛰어나지 않은 듯 하다.
큰 파일을 저장할때, 파일을 Chunk 단위로 나눠서 다운로드, 업로드 하는데 이는 메모리 사용면에서 효율성을 제공한다. (한꺼번에 다 읽거나 쓸때 한꺼번에 Flush를 하면 파일을 메모리에 가지고 있는 동안, 파일 사이즈가 크면 Out Of Memory를 유발할 수 있기 때문에..) 1.7 버전 이하에서는 4M, 1.7 이상에서는 16M의 Chunk Size를 제공하는 것 같은데.
문제는 Opendedup에서도 테스트해봤지만, 이 Chunk 단위로 파일을 나누는 작업이 보통 일이 아니라는, 일단 태생 자체가 작은 Blob 데이타를 저장하기 위함이지 대용량 파일을 저장하기 위함은 아닌 것 같은데,
http://blog.wordnik.com/12-months-with-mongodb 블로그를 보면 12billion (약 120억개)의 레코드를 저장하고, 여기에 음악 파일을 저장하는 것을 보면 가능하다고도 볼 수 있다. 보통 음악 파일이 4M 안팍인것을 감안하면 괜찮은 시나리오인 듯 하나 500GB가 넘어가는 비디오 파일을 저장할때는 어느정도 성능을 감당할 수 있을지는 미지수 이다.
만약에 안정적으로 GridFS가 대용량 파일을 저장할 수 있는 구조를 제공한다면 사람들이 SWIFT,MogileFS,GlusterFS를 사용하지 않고 모두 MongoDB를 사용해야 하지 않을까?
이 부분은 나름 테스트가 필요한 부분으로 남겨놓고 넘어간다.

Querying
아울러 RDBMS 와 같은 Query를 제공한다. (물론 RDBMS보다 한참 못 미치기는 하지만)
Key/Value Store만 지원하는 다른 NoSQL에 비하면 매력 적인 기능

Replication
http://www.mongodb.org/display/DOCS/Master+Slave
Master-Slave Replication도 지원하네, Query Off Loading 구현도 가능하겠다.

Sharding
그외에 자체적으로 데이타 Sharding 아키텍쳐를 지원한다. 요즘 이게 유행인지 MySQL 최신 버전도 자체적으로 Sharding을 지원한다. Sharding을 사용하면 1000개의 Shard까지는 거뜬히 지원할 수 있는 것 처럼 나오는데, 이건 테스트 하기는 어려울테고, 성능 데이타를 레퍼런스 하는 수 밖에

일단 완성도나 기능들이 높아 보이는 것 같은데..
깔아서 테스트해보고, 10gen 에서 컨설팅 불러서 직접 들여다 봐야 몬가 나오지 않을까?
=== 첨언 ===
구조를 살펴보니, 앞에서 언급했던 것처럼 SWIFT나 MogileFS와 상당히 유사하다
앞단에 Load Balancing 역할을 해주는 mongos 라는 프로세스들이 뜨고
뒷단에 실제 데이타를 저장하는 mongod라는 프로세스들이 뜨는데, 여기서 재미있는 것은 데이타 Replication을 하는데, 각 Shard당 3개의 인스턴스를 제공하도록 구성을 권장한다. Swift등에서 흔히 이야기 하는 3 Copy다. 데이타 안정성등을 위하는 건데. (딱 봐도, 하드웨어 비용이 장난 아니겠다.)

더불어서 MogoDB는 Cassandra나 HBase에 비해서 나은 성능을 갖는데 앞에서 설명한 바와 같이 Memory를 이용한 Indexing등으로, 반대로 이야기 하면 Memory가 충분히 있어야 한다는 이야기고, 비싸다는 이야기다.

큐브리드 블로그에 보면 재미있는 내용이 있는데 http://blog.cubrid.org/dev-platform/nosql-benchmarking/

Cassandra and HBase is for processing full-scale large amounts of data, while MongoDB can be used quickly, schema-free when using a certain amount of data.

MongoDB adopts a documented-oriented format, so it is more similar to RDBMS than a key-value or column oriented format.

MongoDB operates on a memory base and places high performance above data scalability. If reading and writing is conducted within the usable memory, then high-performance is possible. However, performance is not guaranteed if operations exceed the given memory. Therefore, MongoDB should be used as a medium or small-sized storage system.

한마디로, 성능은 좋지만 빅데이타는 Cassandra나 HBase를 쓰고 중소형에만 MongoDB를 쓰라는 것이다.
RDBMS에 유사하고 강력한 Feature, 사용의 편리성의 입장에서 MongoDB가 국내외에서 많은 사용층을 가지고 있는 것이 대강 이해는 된다. 한편으로는 MongoDB의 한계를 벗어날만한 데이타를 아직까지 사용해본 적이 없다는 반증도 될것이다. 10~20억 데이타는 내가 아는한에서는 RDBMS에서도 크게 문제가 없다. 문제는 10~20억을 넘는 100억, 1000억개의 데이타 핸들링에도 MongoDB가 버텨 줄것이냐인데.. 데이타 한건당 대략 10K만 잡아도 용량이 1Peta 이다. 3TB 노드를 300개 정도 연결해야 한다는 것인데... MongoDB에서 보통 1000개의 Instance를 이야기를 하니 이론상으로는 가능할것 같기는 한데
첫번째는 어렵지 않을까? 하는 생각이고, (그만한 레퍼런스가 있냐?) 두번째는 만약에 된다고 하더라도 돈이 엄청 들어갈것 같은 느낌이다. Swift도 MogileFS도 저가라고는 말하지만 소프트웨어가 저가인거지 3Copy로 하드웨어 구성을 벤더 제품으로 하면 마찬가지라는... (Commodity 하드웨어라면 몰라도..)
  이래 저래 자료를 찾아볼 필요가 있다.



저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

Mongo DB

클라우드 컴퓨팅 & NoSQL/MongoDB | 2011.03.24 13:55 | Posted by 조대협
점심 시간에, 후욱 훝어봤는데, 생각보다 괴안은 듯.
주요 특징을 적어보면
  • Cassandra와 같은 NoSQL DB와 유사한 데이타 저장 구조를 가진다.
  • 무엇 보다 마음에 드는 건, Sharding과 Replication을 솔루션 차원에서 지원하고,
  • 자체 Map & Reduce 엔진을 가지고 있다.
  • 여기에 더해서, 가장 많은 레퍼런스를 가지고 있다는 것
  • C# 인터페이스가 없는 것이 아쉽기는 한데... C/C++이 있으니, COM으로 만들어서 재 사용해도 될듯.

시간 나면 한번 더 조사해봐야 쓰겄다.
특히 Geo Replication이 되는지가 젤 궁금하네.


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
 

티스토리 툴바