2013년 7월 26일 금요일

MongoDB Architecturing

구조를 설계할때는 먼저 닥치고 그림으로 표현 가능해야 합니다.

깔아보고 만져봐야 그림이 나온다? 맞습니다. 깔아보고 만져보고  꼭 그리세요 

그냥 만지다가 그걸로 프로덕션으로 넘어갔을때 나중에 당할 곤란함을 알고 있다면 

또는 모른다면 여하간 그리는 겁니다.

아래 그림은 가상화서버(Citrix Xen)으로 서버 5개를 만들고(외곽 점선) 각 서버에 노드들을 구성한 구조 입니다.

라우터는 각 서버에 하나씩 다  구성하고 Config는 3개(최대 3개-1개 아니면 3개만 허용함 2개 만들면 안뜬다)  그리고 ReplicaSet을 Sun Moon Mars로 이름지어서 3개 만들었습니다.

각 Set는 내부적으로 Master 노드 1, 복제노드 2, 아비터 노드 1 로 구성합니다.

각 노드에 대한 설명을 써봅니다.

mongoS : 인입된 쿼리를 여러 개의 MongoD(DB)에 분산(라우팅)함, 데이터 저장하지 않음
Configuration Server : 분산 저장되는 데이터(Collection)의 위치를(메타데이터) 저장하고 있음,  MongoS로 인입된 쿼리의 데이터를 조회하기 위한 참조정보로 사용됨

Mongod : 실제 DB 정보의 저장 및 회신을 담당하며

MASTER : R/W가 가능한 Master (node type Standard)

STANDARD SLAVE : Read only이나 장애시 Master로 승격되는 Slave (node type Standard)

PASSIVE SLAVE : Slave이지만 Priority가 0 으로 설정되어 Master를 복제하지만 Master로 승격되지 못하는 Passive  (백업 또는 읽기전용 서버로 사용)

ARBITER : Master장애시 Master로 승격할 Slave 선출에만 참여하고 데이터는 없는 아비터


u설치 구성의 전체 절차
서비스를 위하여 서버를 설치 하는데 있어 MongoDB는 친절하지 않다.
설치는 설치대로 구성 하고 구성정보는 DB에 별도로 입력 하여 구성한다.
전체적인 절차는 아래와 같다.
1.DB 환경 설계
1.Shard 구성방안 Mongos 구성 Config 구성 몇 대  어디로 분산 할 것인가 (HA에 주안점을 둘 것)
2.Replication Set 구성안 MongoD를 몇 개 구성할 것인가, Arbiter 의 위치(HA)
3.대량의 Write 대응 Replset을 늘린다.
4.대량의 Read 대응 Replset내에 Slave를 추가한다.
2.장비준비
1.IP할당
2.OS설치(Cento6버젼이상) 및 튜닝  (본 건의 경우 XenServer를 사용하여 가상화 환경에서 진행)
3.Gluster 또는 NAS 등의 공유저장소 (Local을 사용해도 가능하나 bigData 처리시 Disk 부족으로 인하여 서버를 증설하는 케이스를 줄이기 위해서는 Scale Out가능한 Storage를 구성함이 권장됨
3.서버 설치 및 인스턴스 구동
1.ConfigServer 구성
1.Config 구동 후 Mongos를 띄울때 GlusterFS를 사용하는 경우 Fuse의 MMAP 지원문제로 다운되어 버리는 경우가 있다.
2.이 경우 Linux의 Kernel FUSE의 MMAP 호환성 문제로 판단됨  상세한 원인은 모르나 .CentoOS 6으로 설치하여 문제가 해결됨버전 업그레이드 할 것
2.MongoS 구성
3.ReplicaSet 구성
4.Shard 구성
1.mongoS에 접속하여 Replica Set을 등록하여 실제 데이터 적제 및 조회가 가능하도록 하는 작업 수행
4.개발진행시 샤딩구성(enablesharding) 및 샤드키 등록
1.샤딩하여 저장할 DB를 생성한 다음에 mongoS에서 샤딩 정보를 등록하여 분산 저장하도록 한다.

uConfig SVR  구성
공통
각서버에 mongo 계정을 생성하고 /db 파티션과 /dbdata  /log 파티션을 생성
Db설치위치 : /db/mongodb/
Dbdata위치 : /dbdata/config or instance(실 서비스 DB데이터GlusterFS & FUSE 사용 접속
vlogdb1에서
$ mkdir -p /dbdata/config/config1
mongod --fork --quiet --dbpath /dbdata/config/config1 --port 13000 --configsvr --logpath /log/db/config1.log
vlogdb2에서
$ mkdir -p /dbdata/config/config2
mongod --fork --quiet --dbpath /dbdata/config/config2 --port 13000 --configsvr --logpath /log/db/config2.log
vlogdb3에서
$ mkdir -p /dbdata/config/config3
mongod --fork --quiet --dbpath /dbdata/config/config3 --port 13000 --configsvr --logpath /log/db/config3.log
설명
--fork : processbackground로 실행 (& 없이)
--quiet : 로그를 단순하게 출력
--dbpath /dbdata/config/config3 : Data 저장 위치 PATH
--port 13000  : 서비스 포트 (mongoS 구성시 참조하는 정보)
--configsvr  : mongodDBConfig에 같이 사용함 configserver임을 명시함
--logpath /log/db/config3.log : 로그 저장 위치
기타
Config Server1대 또는 3대 만 허용한다. 2대 또는 4대 이상 구성시 mongos 구동시 오류출력하고 구동 되지 않는다.
Mongodb 자체의 제약 사항이므로 metadata 병목이 우려될 경우 Config 새로운 DB를 별도로 구성하여 운영 하도록 한다.
umongos SVR  구성
공통
각서버에 mongo 계정을 생성하고 /db 파티션과 /dbdata 파티션을 생성
Db설치위치 : /db/mongodb/
Dbdata위치 : mongosdata 저장소를 사용하지 않는다.
mdbs1에서
mongos --fork --quiet --port 15000  --configdb mdbs1:13000,mdbs2:13000,mdbd1:13000 --logpath /log/db/route1.log
mdbs2에서
mongos --fork --quiet --port 15000  --configdb mdbs1:13000,mdbs2:13000,mdbd1:13000 --logpath /log/db/route2.log
설명
--fork : processbackground로 실행 (& 없이)
--quiet : 로그를 단순하게 출력
--port 15000  : 서비스 포트 (mongoS 구성시 참조하는 정보)
--configdb mdbs1:13000,mdbs2:13000,mdbd1:13000  : config서버 정보를 리스팅 한다. 분산파일을 찾아 낼 때 사용함
--logpath /log/db/config3.log : 로그 저장 위치
기타
Mongos는 여러대가 구성 가능하다
권장하는 구성은 모든 서버에 mongos를 구성하는 것이다.
분산을 위해서는 L4등에 등록이 필요하지만 궂이 모두 등록 하지 않아도 되며 HA를 감안하여 구성
Config Server 정보는 1대 또는 3대 만 허용한다. 2대 또는 4대 이상 구성시 mongos 구동시 오류출력하고 구동 되지 않는다.
uReplication Set 구성
설명
기본 제공되는 HA 방식인 MASTER/SLAVE 구성은 Master 파손시 Write가 되지 않도록 구성된다.
ReplSet 구성시 Master(PRIMARY라고 한다) 파손에 따른 승급( Promotion)이 자동으로 동작한다.
1개의 MasterN(12개이하) Slave, 1개의 Arbiter로 구성된 ReplSet는 다수 구성될 수 있다.
Shard Server 구성시에는 Master Slave구동시 지정하지 않고 replSet 으로 상호간의 정보를 등록한다.
Master는 임의로 지정(선출/자동)되거나 앞서 ReplSet구성시 priority를 높게 지정한 서버가 Master가 된다.
데이터 저장소 생성
MongoDB (글러스터FSNAS를 사용하는 경우 아무대 서나 한곳에서(단독에서는 각각 필요한 경우만)
“sun” ReplSet
$ mkdir -p /dbdata/instance/sun/abit  (arbiter)
$ mkdir -p /dbdata/instance/sun/vlogdb2
$ mkdir -p /dbdata/instance/sun/vlogdb4
$ mkdir -p /dbdata/instance/sun/vlogdb5
moon/mars 용으로 폴더 생성
구성
vlogdb1에서
$ mongod  --dbpath /dbdata/instance/sun/abit --port 10000 --fork --quiet --logpath /log/db/sun_abit.log --replSet sun/vlogdb4:10001,vlogdb2:10002,vlogdb5:10002
$ mongod --dbpath /dbdata/instance/moon/vlogdb1 --port 20002 --fork --quiet --logpath /log/db/moon_slave.log --nssize 1024 --oplogSize 2048 --replSet moon/vlogdb3:20001,vlogdb4:20002
vlogdb2에서
$ mongod  --dbpath /dbdata/instance/sun/vlogdb2 --port 10002 --fork --quiet --logpath /log/db/sun_slave.log --nssize 1024 --oplogSize 2048 --replSet sun/vlogdb4:10001,vlogdb5:10002
$ mongod  --dbpath /dbdata/instance/moon/arbit --port 20000 --fork --quiet --logpath /log/db/moon_arbit.log --replSet moon/vlogdb3:20001,vlogdb1:20002,vlogdb4:20002
$ mongod --dbpath /dbdata/instance/mars/vlogdb2 --port 30002 --fork --quiet --logpath /log/db/mars_slave.log --nssize 1024 --oplogSize 2048 --replSet mars/vlogdb4:30002,vlogdb5:30001
Vlogdb3에서
$ mongod --dbpath /dbdata/instance/moon/vlogdb3 --port 20001 --fork --quiet --logpath /log/db/moon_master.log --nssize 1024 --oplogSize 2048 --replSet moon/vlogdb1:20002,vlogdb4:20002
$ mongod --dbpath /dbdata/instance/mars/abit --port 30000 --fork --quiet --logpath /log/db/mars_arbit.log --replSet mars/vlogdb2:30002,vlogdb4:30002,vlogdb5:30001
Vlogdb4에서
$ mongod --dbpath /dbdata/instance/sun/vlogdb4 --port 10001 --fork --quiet --logpath /log/db/sun_master.log --nssize 1024 --oplogSize 2048 --replSet sun/vlogdb2:10002,vlogdb5:10002
$ mongod --dbpath /dbdata/instance/moon/vlogdb4 --port 20002 --fork --quiet --logpath /log/db/moon_slave.log --nssize 1024 --oplogSize 2048 --replSet moon/vlogdb1:20002,vlogdb3:20001
$ mongod --dbpath /dbdata/instance/mars/vlogdb4 --port 30002 --fork --quiet --logpath /log/db/mars_slave.log --nssize 1024 --oplogSize 2048 --replSet mars/vlogdb2:30002,vlogdb5:30001
Vlogdb5에서
$ mongod --dbpath /dbdata/instance/sun/vlogdb5 --port 10002 --fork --quiet --logpath /log/db/sun_slave.log --nssize 1024 --oplogSize 2048 --replSet sun/vlogdb2:10002,vlogdb4:10001
$ mongod --dbpath /dbdata/instance/mars/vlogdb5 --port 30001 --fork --quiet --logpath /log/db/mars_master.log --nssize 1024 --oplogSize 2048 --replSet

uReplication Set 구성 – SUN setting
“SUN” ReplSet  Init
실제 DB 내부에 설정을 초기화 한다.

//구성된 DB 중에서  SUN Replication Set을 만든다.
//start replSet으로 사용할 DB아무대나 접속해서 된다. 아래 예에서는 Master로 사용할 DB에서
//접속
./mongo vlogdb4:10001/admin  ç MASTER / SLAVE 아무곳에서 해도 되나 그냥 MASTER에서 진행했음
//아래 컴멘드를~ 넣어 주면 됨, 한줄로 안 넣어도 됨
>db.runCommand({"replSetInitiate":
  {"_id":"sun",
  "members":[
  {
      "_id":0,
      "host":"vlogdb1:10000",
      "arbiterOnly":true
  },
  {
      "_id":1,
      "host":"vlogdb2:10002"
  },
  {
      "_id":2,
      "host":"vlogdb4:10001",
      "priority":100    ç  이 숫자가 높은 녀석이  PRIMARY 가 된다.(default 1)
  },
  {
      "_id":3,
      "host":"vlogdb5:10002"
  }
  ]
  }})
//명령수행 결과
{
        "info" : "Config now saved locally.  Should come online in about a minute.",
        "ok" : 1
}

Moon 하고 Mars도 위를 참고해서 구성하면 됩니다.  포트와 hostname에 주의 하세요

uShard Server구성
설명
mongoS에서 요청들어온 데이터를 분산저장 하거나 찾아 내기 위해서 Shard구성을 한다.
Shard 구성은  mongoSReplSet 정보를 등록함으로써 수행된다.
mongoS에 접속하여 정보를 입력하면 해당 정보는 ConfigSVR에 저장된다.
mongoS가 여러대 이더라도 1대에 Shard용 서버 또는 ReplSet 정보를 등록하면 자동으로 전파되어 동기화 된다.(작업은 1곳에서 1)
구성
//mongoS 서버 중에 아무대나 접속한다. 아래의 경우 1번에 접속
./mongo vlogdb1:15000/admin
//”sun” replSet을 등록한다
>db.runCommand({addshard:"sun/vlogdb4:10001"})
//”moon” replSet을 등록한다
>db.runCommand({addshard:"moon/vlogdb3:20001"})
//”mars” replSet을 등록한다
>db.runCommand({addshard:"mars/vlogdb5:30001"})
======================
logdb샤딩한다고 정의 안하면 계속 첫번째 샤드에 저장
db.runCommand({"enablesharding":"logdb"})
샤드할 콜랙션과 키를 지정한다.
db.runCommand({"shardcollection":"logdb.weblogColl", "key":{"_id":1}})

위의 경우 vlogdb1,2,3,4,5 정보를 /etc/hosts 파일에 등록해 놓았다. (아니면 IP 넣어야 함)
여러 개의 mongod 서버 중에서 아무 서버나 등록해서 Replication SET 정보를 알아내기는 하지만 관리상 임의로 Master로 지정한 서버의 정보를 등록 하였다.
위와 같이 해 놓으면 Replica set 서버 중에서 어느 놈이 죽더라도 set안에 다른 서버가 Master로 승격되고 알아서 그쪽으로 Write를 전달 하게 된다.(자동 처리됨, 테스트 결과 5초 미만)

단순하게 데이터를 입력하기 위한 코드 셈플입니다.

import java.net.UnknownHostException;
import java.util.Set;
import com.mongodb.*;
public class mongoTest {
    public static void main(String[] args) throws Exception {
  try{
  Mongo m = new Mongo(“172.18.186.193",15000);
                           DB db = m.getDB("logdb");
 
                                                                         Set<String> colls = db.getCollectionNames();
                                                                                for (String s : colls) {
                                                                                          System.out.println(s);
                                                                                          }
                                                                       // get a collection object to work with
                                                                        DBCollection coll = db.getCollection("weblogColl");
  BasicDBObject doc = new BasicDBObject();
  doc.put("IP", "127.0.0.1");
  doc.put("DATE", "17/Oct/2011");
  doc.put("TIME", "15:17:55");
  doc.put("ZONE", "+0900");
  doc.put("URI", "/test.xxx");
  doc.put("VERSION", "HTTP/1.1");
  doc.put("CODE", "404");
  doc.put("SIZE", "208");
 
  coll.insert(doc);
 
  }catch(UnknownHostException e){
  System.out.println("Unknown Host!!");
  }
       
  }//mongoDbConnectionTest
 
}                       


구동할때 마다 손으로 하면 힘드니까 스크립트를 만들어서 구동하고 정지하세요 
스크립트 셈플로 하나 올립니다. 

#!/bin/sh
#START MONGO DB INSTANCE
# Check user
#######################################
USER=`whoami`
if [ $USER != "mongo" ]; then
  echo "$0 should be running as [mongo] user. " >&2
  exit 9
fi
######################################
PROGRAM=/db/mongodb/bin/mongod
MONGOPID=`ps -ef | grep 'mongod' | grep 'moon_slave' | grep -v grep | awk '{print $2}'`
test -x $PROGRAM || exit 0
case "$1" in
  start)
     echo "Starting replSet MOON DB server"
     $PROGRAM --dbpath /dbdata/instance/moon/vlogdb1 --port 20002 --fork --quiet --logpath /log/db/moon_slave.log --nssize 1024 --oplogSize 2048 --replSet moon/vlogdb3:20001,vlogdb4:20002
     ;;
  stop)
     echo "Stopping replSet MOON DB server"
     if [ ! -z "$MONGOPID" ]; then
        kill -15 $MONGOPID
     fi
     ;;
  *)
     echo "Usage:moon_slave.sh {start|stop}"
     exit 1
esac
exit 0

ㄴㅇㄹㅇㄴㅁㄴ





댓글 1개:

  1. Replication Set 구성시 서버갯수는 홀수로 해야합니다.
    현재 마스터 1+ 슬레이브 2 면 홀수이기 때문에 아비터가 필요없습니다.

    답글삭제

본 블로그의 댓글은 검토후 등록됩니다.