샤딩 (Sharding) 을 하는 방법 또는 복제 셋 (Replication) 을 하는 방법에 관한 예제는 잘 나와 있습니다. 그런데 실전에서는 복제와 샤딩을 동시에 하는 것이 일반적일 것입니다. 이것에 관한 예제가  많이 없더군요. 어쩌다 찾은 것이 한개 있지만 한 기계에서 가상으로 돌려보는 예제 입니다. 이러한 예제로는 샤딩을 제대로 테스트 할 수가 없더군요. 하지만 그 문서를 바탕으로 실제로 샤딩과 복제를 클러스터 환경에서 테스트 해 봤습니다. 

http://cookbook.mongodb.org/operations/convert-replica-set-to-replicated-shard-cluster/ 

위 내용은 한 기계안에서 샤딩과 복제 셋을 테스트 하는 예제 입니다. 


원칙대로라면 복제 셋 (Replication Set) 을 설정할 때 한 머신에서 동작시키는 것이 아니라 서로 다른  서버에서 구동되게 설계를 해야 하지만 그것 까지 세팅하기가 매우 귀찮기 때문에 다음 과 같이 설계를 해 봤습니다. 

   

    Machine 1 : 

    - name : super1
    - replication : first * 3


    Machine 2 :

    - name : super2
    - replication : second * 3

    


 

 즉 2대의 머신에서 샤딩이 이루어 지게 세팅을 하는 것인데, 각각의 머신은 3개의 복제 셋을 가지게 구성 되는 것입니다. 

mongoDB 의 bin 이 path 에 걸려 있다는 가정 하에 진행 합니다. 

super1 부터 설정을 시작합니다.
  먼저 데이터들이 저장될 db 디렉토리를 만들어 줍니다. 

   

    $ mkdir ~/db/first1 
    $ mkdir ~/db/first2
    $ mkdir ~/db/first3

    
    로그를 저장할 공간도 만들어 줍니다. 

    $ mkdir ~/db/log 


    이제 몽고 데몬들을 띄워줍니다. 

 

    $ mongod --dbpath ~/db/first1 --port 10001 --replSet first > ~/db/log/first1.log &
    $ mongod --dbpath ~/db/first2 --port 10002 --replSet first > ~/db/log/first2.log &
    $ mongod --dbpath ~/db/first3 --port 10003 --replSet first > ~/db/log/first3.log &


    이제 이 세개의 몽고 디비 프로세스들을 한개의 복제셋 (여기서는 first )으로 묶어주는 작업을 합니다. 

 

  $ mongo localhost:10001/admin 

    > db.runCommand({"replSetInitiate" : {"_id" : "first", "members" : [{"_id" : 1, "host" : "super1:10001"}, {"_id" : 2, "host" : "super1:10002"}, {"_id" : 3, "host" : "super1:10003"}]}})
    {
        "info" : "Config now saved locally.  Should come online in about a minute.",
"ok" : 1
    }


    이러면 성공적으로 복제 셋이 만들어 진것 입니다. 이제 데이타를 실제로 넣어보기로 하겠습니다. 

   

PRIMARY> use test
    switched to db test
    PRIMARY> people = ["Marc", "Bill", "George", "Eliot", "Matt", "Trey", "Tracy", "Greg", "Steve", "Kristina", "Katie", "Jeff"];
    PRIMARY> for(var i=0; i<1000000; i++){
          name = people[Math.floor(Math.random()*people.length)];
 user_id = i;
 boolean = [true, false][Math.floor(Math.random()*2)];
 added_at = new Date();
 number = Math.floor(Math.random()*10001);
 db.test_collection.save({"name":name, "user_id":user_id, "boolean": boolean, "added_at":added_at, "number":number });
    }

 
    이름을 백만건 정도 랜덤으로 순서를 매겨서 집어넣는 소스코드 입니다. 


이제는 구성된 복제 셋을 가지고 샤딩으로 추가해 주는 작업을 해 줘야 할 차례 입니다. 역시  super1  서버에서 작업을 해 줍니다. 

config 서버를 띄워줄 차례 입니다. 먼저 config 데이타들이 저장 될 디렉토리를 만들어 줘야 합니다. 

   $ mkdir ~/db/config1
   $ mkdir ~/db/config2
   $ mkdir ~/db/config3


컨피그 서버는 1대 아니면 3대를 추천합니다. (제가 아니라 몽고디비 쪽이 추천하는 것입니다) 

 

   $ mongod --configsvr --dbpath ~/db/config1 --port 20001 > ~/db/log/config1.log &
   $ mongod --configsvr --dbpath ~/db/config2 --port 20002 > ~/db/log/config2.log &
   $ mongod --configsvr --dbpath ~/db/config3 --port 20003 > ~/db/log/config3.log &


혹시 컨피그 서버가 제대로 띄워지지 않으면 다른 포트로 띄워주시면 됩니다. 이제 컨피그 서버에서 정보를 가져오는 mongos (라우터 개념)를 띄워줄 차례 입니다. 

 

 $ mongos --configdb super1:20001,super2:20002,super3:20003 --chunkSize 1 > ~/db/log/mongos.log &


 chunkSize 는 테스트에서만 추가하는 것으로 생각하시면 됩니다. 크기를 1메가로 만드는  것입니다. (기본은 64메가 입니다) 이제 띄워논 mongos 에 접속해야 한다. 

 

 $ mongo super1/admin
  
 mongos> db.runCommand( { addshard : "first/super1:10001,super2:10002,super3:10003" } )

   { "shardAdded" : "first", "ok" : 1 }
   mongos>
   
  
이제 두번째 기계에서 세팅을 할 차례 입니다. super2 (Machine 2) 입니다.  먼저 데이타베이스가 저장될 디렉토리를 만들어 줍니다. 

   

   $ mkdir ~/db/second1 
   $ mkdir ~/db/second2
   $ mkdir ~/db/second3 
   

로그용 디렉토리도 만들어 줍니다. 
   

$ mkdir ~/db/log 


몽고디비 데몬을 띄워줍니다. 

   

   $ mongod --dbpath ~/db/second1 --port 10001 --replSet second > ~/db/log/second1.log &
   $ mongod --dbpath ~/db/second2 --port 10002 --replSet second > ~/db/log/second2.log &
   $ mongod --dbpath ~/db/second3 --port 10003 --replSet second > ~/db/log/second3.log &


이제 이 프로세스들을 한 개의 복제 셋(replication set)으로 묶어 줍니다. 

 

 $ mongo super2:10001/admin

   > db.runCommand({"replSetInitiate" : {"_id" : "second", "members" : [{"_id" : 1, "host" : "super2:10001"}, {"_id" : 2, "host" : "super2:10002"}, {"_id" : 3, "host" : "super2:10003"}]}})
   {
      "info" : "Config now saved locally.  Should come online in about a minute.",
      "ok" : 1
   }



방금 만들어 진 복제 셋 (replication set) 을 새롭게 샤드 (shard) 에 추가해 줍니다. 먼저 mongos 를 띄워줍니다. 지금 super2 서버고 mongos 도 super2 에서 띄우는 것이지만 바라보는 컨피그 서버 는 super1 에서 띄운 것을 쳐다봐야 합니다. 

   $ mongos --configdb super1:20001,super2:20002,super3:20003 --chunkSize 1 >  ~/db/log/mongos.log &


몽고 shell 을 이용해서 mongos (이건 super2 에 띄워 놓은 것입니다) 에 접속합니다. 

   

$ mongo super2/admin
   mongos> use admin
   switched to db admin
   mongos> db.runCommand( { addshard : "second/super2:10001,super2:10002,super3:10003" } )
     { "shardAdded" : "secondset", "ok" : 1 }


이러면 두번째 복제 셋 (replication set) 을 샤드에 추가 해 주었습니다.  제대로 되어 있는지 테스트를 확인 해 보기로 합니다. 

 

 mongos> db.runCommand({listshards:1})
   {
        "shards" : [
  {
      "_id" : "first",
      "host" : "first/super1:10001,super1:10003,super1:10002"
  },
  {
      "_id" : "second",
      "host" : "second/super2:10001,super2:10002,super2:10003"
  }
     ],
     "ok" : 1
   }


샤드로 설정되어 있는 것하고 샤드를 직접적으로 하는 것은 차이가 있습니다. 실제로 샤드를 구현해 보겠습니다. mongos 에 접속되어 있는 상태에서 

 

 mongos> db.runCommand( { enablesharding : "test" } )
   { "ok" : 1 }


 
위 처럼 입력해 주면 'test' db 를 샤딩하겠다고 정해주는 것입니다. 이제 샤딩 키 (Sharding Key) 를 정해줘야 합니다. 샤딩 키를 바탕으로 (이 키로 정렬한다는 뜻입니다) 샤드들이 나눠지게 되기 때문에 샤딩키를 적절하게 정해주는 것은 아주 중요합니다. 인덱스를 정해준다고 보셔도 무방합니다. 

 

   mongos> use test
   switched to db test
   mongos> db.test_collection.ensureIndex({number:1})

   
   생각 난 김에 인덱스도 정해줍니다. test 디비에 test_collection 이라는 컬렉션에서 number 라는 컬럼을
   인덱스로 지정해 주라는 명령입니다. 

   

mongos> use admin
   switched to db admin
   mongos> db.runCommand( { shardcollection : "test.test_collection", key : {"number":1} })
   { "collectionsharded" : "test.test_collection", "ok" : 1 }
   mongos>


   
test 디비에 test_collection 이라는 컬렉션에서 number 라는 컬럼을 샤딩키로 해서 샤딩을 해 주라는 명령입니다. 

제대로 됐는지 확인을 해 보겠습니다. 

 

   mongos> use test
   switched to db test
   mongos> db.stats()


   
db.stats() 나 db.printShardingStatus() 로 확인하시면 됩니다. 


+ Recent posts