'몽고'에 해당되는 글 7건

  1. 2015.11.20 :: mongodb mapreduce(2)
  2. 2015.11.20 :: mongodb mapreduce(1)
  3. 2015.11.20 :: mongodb aggregation(2)
  4. 2015.11.20 :: mongodb sharding 작업 및 확인
  5. 2015.11.19 :: mongodb cluster(4)
  6. 2015.11.19 :: mongo cluster(2)
  7. 2015.11.19 :: mongoDB cluster (1)
개발관련/MongoDB 2015. 11. 20. 16:40

먼저 collections를 확인해보자. 

1
2
3
4
5
6
7
show collections
 
//result
testReduce
users
 
 
cs

show collections를 하면 결과가 나온다. 앞서 만든 mapreduce에 사용한 testReduce와 데이타를 저장한 users가 존재한다. 


그럼 system.js를 만들어보자. 앞서 만들어놓은 함수들을 어딘가 복사해놓자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 
db.system.js.insert(
    [
        {
            _id: "map",
            value : function () {
             
              var key = {};
              key.eyeColor = this.eyeColor;
              key.gender = this.gender;
              
              var value = {};
              value.age = this.age;
              value.count = 1;
              emit(key, value);
            }
        },
        {
            _id: "reduce",
            value : function (key, values){
                var returnVal = {};
                var totalAge =0;
                var totalCount = 0;
                for( index in values){
                    totalAge += values[index].age;
                    totalCount += values[index].count;
                }
               
                return {"age":totalAge , "count" : totalCount};
                
            }
        },
        {
            _id : "finalize",
            value : function(key, values){
                return {
                    "age" : values.age,
                    "count" : values.count,
                    "avg" :  values.age/values.count
                };
            }
        }
    ]
);
 
 
 
cs

위 형태로 system.js 라는 collections에 저장하자. 이때 앞의 함수와 틀린점은 "_id"가 존재하며 여기에 앞서 사용한 변수명이 들어간다. value부분에 함수가 들어간다. 

여기까지 했으면 다시 collections를 확인해보자. 
1
2
3
4
5
6
 
system.indexes
system.js
testReduce
users
 
cs

system.js 라는 collections과 indexes라는넘이 추가되었다. 


이제 mapReduce를 하기전에 마지막으로 위에 값들을 load 를 해야한다. 


1
2
 
db.loadServerScripts();
cs


위에 구문을 쓰면 몽고 디비의 서버에 맵리듀스 함수가 로드 된것이다. 

그럼 map,reduce, finalize 라는 _id의 값은 어떻게 되있는지 확인하자 

map; reduce; finalize; 라는 명령으로 확인하면 다음과 같은 결과를 확인 할 수 있다. 

아래는 map; 의 함수를 보여주고있다. 

1
2
3
4
5
6
7
8
9
10
function __cf__13__f__anonymous_function() {
    var key = {};
    key.eyeColor = this.eyeColor;
    key.gender = this.gender;
    var value = {};
    value.age = this.age;
    value.count = 1;
    emit(key, value);
}
 
cs



이제 다시한번 mapreduce를 하는데 이번엔 out의 옵션을 좀 추가해보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
db.users.mapReduce(
    map,reduce, 
    {
        
       
        out : {
            reduce : "testReduce"
            
        },
        //map들어갈 collection 필터링 할때 
        query : {
            "index" : {
                $gte : 1000
            }
        },
        //가령 추천수가 가장 많은 사람을 쓸때 오름 차순으로 하면 제일 먼저 나오는 사람이 젤위이므로 이 사람을 빨리 가져올때 사용.
        //sort : {},
        //reduce 를 한 결과를 가공을 할때 사용. 
        finalize : finalize,
        //scope는 map, reduce, finalize 함수의 전역 변수로 사용된다. 
        //사용시는 $변수명으로 사용하면된다. 
        //scope: { "temp" : 1},
        //몽고디비는 bson 타입으로 저장을한다. 이때 속도가 좀 걸리는데 json 형태로 할것인지를 선택하는 옵션이다. 
        //그러나 json의 경우 속도는 빠르나 collection document의 제한이 걸린다. 그래서 안쓰는게 상책.
        //jsMode: <boolean>,
        //verbose: <boolean>
    }
);
 
 
cs


out의 옵션에 reduce를 주고 "testReduce" collection명을 주었다. 실행하면 결과는 testReduce로 저장될 것이다. 이제 


db.testReduce.find()로 값을 확인하자. 


아까 값에 reduce 된 값이 보일것이다. 


후 여기까지..... 

posted by 제스트
:
개발관련/MongoDB 2015. 11. 20. 16:18

mapreduce는 map 과 reduce의 합성어 이다. 

map은 특정 collection의 특정 key 와 value를 map으로 하며, map의 key는 중복이 안되며, value는 list에 쌓이는 형태로 된다. 


reduce는 map의 데이터를 감소 시키는 역활을 한다. reduce를 통해 특정 값을 뽑아낸다.이를 통계치 데이터로 사용하게 된다. 


1
2
3
use dbname
 
db.users.find();
cs
먼저 데이터를 확인한다. 앞서 사용한 collections을 사용할 것이다. 


1
2
3
4
5
6
7
8
9
10
11
{
    "_id" : "564c3240e5aa2a5f7c7bd7f5",
    "index" : 0,
    "isActive" : false,
    "age" : 30,
    "eyeColor" : "green",
    "name" : "Rodgers Grant",
    "gender" : "male",
    "company" : "VERTON",
    "email" : "rodgersgrant@verton.com"
}
cs

자 map을 설계 해보자. 필자는 "각 eyeColor 별로  성별를 구분하고, 전체 나이와 인원을 구하고 싶다" 이 기준으로 먼저 map을 만들어 보자. 
1
2
3
4
5
6
7
8
9
10
11
12
13
//make map 
var map = function () {
  //맵은 단순 key value로 선언을 하며 , 이 값들은 emit을 통해 reduce로 전달을 한다. 
  //this는 현재 collection에 document가 저장된다. 
  var key = {};
  key.eyeColor = this.eyeColor;
  key.gender = this.gender;
  
  var value = {};
  value.age = this.age;
  value.count = 1;
  emit(key, value);
};
cs

어라 js랑 똑같다. 걍 js 함수다 . map이라는 함수에 key에는 eyeColor와 gender를 저장하고, value에는 age와 count를 저장한다. 여기서 눈여겨 볼 껀 this라는 넘이다. 이 this는 현재 사용하고 있는 collection을 뜻하며, 이 collection의 filed명을 쓰면 그 값들이 전달된다.  자 위에 map을 선언 하면 다음과 같은 비슷한 결과 형태로 될것이다. (머 내부적으로 어떻게 저장하는지는 몰라서 ... 추측하건데...=_=;)

1
green.male : [{ 30,1},{36,1}............]
cs

위에 작업이 끝나면 map; 를 실행해보자. 위에 코드가 나올것이다. 
여기에 보면 emit이라는 넘이 있다. 저 emit은 reduce로 값을 전달하며 map의 결과를 reduce 매개변수로 전달하게 된다. 그럼 reduce를 해보자. 

1
2
3
4
5
6
7
8
9
10
11
12
var reduce = function (key, values){
    var returnVal = {};
    var totalAge =0;
    var totalCount = 0;
    for( index in values){
        totalAge += values[index].age;
        totalCount += values[index].count;
    }
    //return type은 map의 기준의 value로 결정되므로 reduce의 return type의 value랑 똑같은 형태로 맞춰줘야한다.!!
    return {"age":totalAge , "count" : totalCount};
    
}
cs

이것도 js함수다. key, values에는 emit으로 전달한 파라미터들이 있다. values에는 배열로 값이 들어있으므로, 위에 예시 처럼 loop문을 돌려주면서 totalage와 totalcount에 전체 나이 전체 인원을 계산한다. reduce의 중요한 사실은 return 값에 있다. 이 리턴은 map에서 이미 정해야 한다. 위의 map의 value를 보자. map의 value는 age와 count이다. 이 value 형태로 return이 되야만한다. 

다시 mapreduce에 대해 정리하자. 
1. map은 key, value를 정의하며 emit으로 전달한다. 이때 value는 reduce의 return값과 동일하다. 
2. reduce는 value에 대해 값을 재정의 할수 있으며, return은 map의 value와 동일해야한다.

여기에는 한계가 있다. reduce의 return이 map의 value와 같으므로 값을 정형화 하지 못한다. 이때 쓰는 함수가 finalize이다. 


1
2
3
4
5
6
7
8
9
 
var finalize = function(key, values){
    return {
        "age" : values.age,
        "count" : values.count,
        "avg" :  values.age/values.count
    };
}
 
cs

finalize는 reduce의 마지막 나온 결과를 건네주게 된다. 여기서 마지막이란 trycatch의 finaliy 정도 생각 하면 되겠다. finalize는 결과를 마음 대로 수정해도 된다. 


자 이제 mapreduce 함수를 호출 해보자. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
db.users.mapReduce(
    map,reduce, 
    {
        //없으면 현재 db에  만든다.
        /**
        *
        out: { <action>: <collectionName>
        [, db: <dbName>]
        [, sharded: <boolean> ]
        [, nonAtomic: <boolean> ] }
        <action>
         replace - 기존의 있는 콜렉션을 없애고 mapreduce결과를 집어 넣는다.
         merge - 이미 있는 콜렉션을 넣는데 현재 키가 존재할경우 오버라이트 한다. 
         reduce - 같이 키로 결과가 있으면 그 결과들 끼리 reduce를 한다. 
         db 
         - output collection 을 쓸 db이름을 정의 default db는 mapreduce collection과 같은 db이다. 
         
         sharded 
         - 맵리듀스 결과 collection을 바로 샤딩하고 싶을때 true로 변경. 
         nonAtomic
         - mapreduce 사용시 true로 사용하면 lock이 걸리지 않는다. (상황에 따라 써야겠구만.)
        **/
        out : "testReduce",
        //map들어갈 collection 필터링 할때 
        query : {
            "index" : {
                $gte : 1000
            }
        },
        //가령 추천수가 가장 많은 사람을 쓸때 오름 차순으로 하면 제일 먼저 나오는 사람이 젤위이므로 이 사람을 빨리 가져올때 사용.
        //sort : {},
        //reduce 를 한 결과를 가공을 할때 사용. 
        finalize : finalize,
        //scope는 map, reduce, finalize 함수의 전역 변수로 사용된다. 
        //사용시는 $변수명으로 사용하면된다. 
        //scope: { "temp" : 1},
        //몽고디비는 bson 타입으로 저장을한다. 이때 속도가 좀 걸리는데 json 형태로 할것인지를 선택하는 옵션이다. 
        //그러나 json의 경우 속도는 빠르나 collection document의 제한이 걸린다. 그래서 안쓰는게 상책.
        //jsMode: <boolean>,
        //verbose: <boolean>
    }
);
 
cs


 파라미터는 총 3개다. map, reduce, 3번째는 object이다. 중요한것은 이 3번째 파라미터...

먼저 out 이라는 넘이 나온다. 단순히 값을 쓰면, 지정한 값으로 collection을 만들고 그 collection에 mapreduce 값을 쓴다. 이때 위에 주석으로 써놓았듯이 옵션에는 총 3가지가 있다. replace, merge, reduce 이 3개가 있는데 default는 replace 로 쓴다. 


query라는 넘은 mapreduce를 할 collection의 값을 특정 결과로 만들고 난 후 mapreduce로 전달한다. 위에 예제는 users collection에 index가 1000 이상인 사람들에 대해 mapreduce를 한다는 예시이다. 


finalize 는 위에 선언해놓은 finalize 함수의 변수를 쓰면 된다. 나머지 옵션은 주석으로 써놓았으니 살펴 보면된다. 


이 mapreduce는 cursor라는 곳에 저장을 한다. 이 cursor는 휘발성이므로  계속적으로 사용 할때는 위와 같이 사용 해서는 안된다. 다음에는 이를 막고자 할때 사용하는 system.js 에 대해 알아본다. 



posted by 제스트
:
개발관련/MongoDB 2015. 11. 20. 13:49

자 이번엔 이전 쿼리에서 평균을 내어 보자. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
db.users.aggregate([
//stage 별로 나뉘며 앞에서 처리 된걸 가지고 다음 stage로 전달
    //stage 1
    {
        $match : {
            "index" :{
                $gte: 10000
            }
        }
    },
//stage2
    {
       $group:{
           "_id" :  "$eyeColor"
           "sum" : {
               $sum : 1
           }
       }
       
    },
//stage3
    {
       $group:{
           "_id" : "$_id",
           "avg" : {
               $avg : "$sum"
           }
       }
       
    }
    
]);   
 
cs


어라.. 먼가 바뀌었다. 위에 $group의 값을 보면 "$eyeColor"가 존재한다. 이 말은 users의 field에 eyeColor 라는넘을 사용하고 싶으면 위의 예시 처럼 사용하면 된다. 마지막 $group에 또 "$sum"이라는 넘이 나온다. 이 "$sum"이 앞서 있던 stage의 key였던 sum이 $sum으로 변경된 것이다. 


결론은 collection의 field 명 -> "$필드명" 이전 statge key 값 -> 다음 stage의 "$key" 로 사용 할 수 있다. 


근데 결과가 이전에 봤던거랑 같다. 이유는 $avg의 평균을 내면 그 값이 나오므로 ... 그럼 진짜 평균을 내보자. "각 eyeColor의 전체나이와 전체 나이의 평균" 을 내어보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
db.users.aggregate([
//stage 별로 나뉘며 앞에서 처리 된걸 가지고 다음 stage로 전달
    //stage 1
    {
        $group : {
            "_id" : "$eyeColor" ,
            "ageSum" : {
                $sum : "$age" 
            },
            "ageCount" : {
                $sum : 1
            }
        }
    },
//stage2
    {
        $project : {
            //"_id" : 1,
            "ageAVG" : {
                $divide : ["$ageSum" ,"$ageCount"]
            }
            
        }
    }
    
]);   
cs


또 새로운게 등장 $project 이넘은 없는 필드를 만들거나 기존 필드를 안보이고 싶을때 사용 한다고 공식사이트에 명시 되있다. 위의 예제를 보면 각 stage별로 값들을 전달한 것들을 알 수있다. 


이걸로 aggregation은 끗.... 

posted by 제스트
:
개발관련/MongoDB 2015. 11. 20. 13:20

저번 글까지는  단순히 cluster 환경 구성을 하는 것이었다.. 이제 데이터를 넣어보자. 


먼저 필자는 다음과 같은 json 구조로 데이터를 10000건을 만들었다. 


1
2
3
4
5
6
7
8
9
10
11
{
    "_id" : "564c3240e5aa2a5f7c7bd7f5",
    "index" : 0,
    "isActive" : false,
    "age" : 30,
    "eyeColor" : "green",
    "name" : "Rodgers Grant",
    "gender" : "male",
    "company" : "VERTON",
    "email" : "rodgersgrant@verton.com"
}
cs


linux 커널에서 다음과 같은 명령으로 데이터를 넣는다. 

1
2
 ./bin/mongoimport -h 192.168.0.105:45005 -d dbname -c collectionName --file ${path}/users.json
 
cs



그런후... 샤드의 상태를 확인해보자. 

1
2
 
sh.status();
cs

아마도, 1개의 샤드에만 들어있을 것이다. 


분명히 2개의 샤드에 분리 되야 하는데.... =_=; 

그럼 chunk의 size를 확인한다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
use config
db.settings.find();
 
//result
{
    "_id" : "chunksize",
    "value" : 64.0000000000000000
}
 
/* 2 */
{
    "_id" : "balancer",
    "stopped" : false
}
cs

use config  이 넘은 cluster server의 내부 db 이다. cluster만 존재하며, 설정 정보들이 들어있다. 

db.settings.fing()를 하면 위의 결과 처럼 나올 것이다. 기본 mongodb의 chunk size는 64M 인것이다. 10000건의 데이터는 3M도 안된다. =_=; 그러므로 샤딩은 당연히 안될것이다. 그럼 한번 줄여보자. 

1
db.settings.save( { _id:"chunksize", value: 1 } );
cs

다시 find로 검색해보면 1M로 바뀌어 있을 것이다. 그럼 sh.status()로 확인해보자.
여전히 샤딩은 안될 것이다. 흠.... 왜 샤딩이 안되지... 자 10000건을 다시 한번 넣어보자. 전체 data양은 20000만건... !!!! 

확인 ... sh.status();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
--- Sharding Status --- 
  sharding version: {
    "_id" : 1,
    "minCompatibleVersion" : 5,
    "currentVersion" : 6,
    "clusterId" : ObjectId("564aff51f77bed76dca6ba70")
}
  shards:
    {  "_id" : "elastic",  "host" : "elastic/192.168.0.105:45001,192.168.0.105:45002,192.168.0.105:45003" }
    {  "_id" : "shard0000",  "host" : "192.168.0.105:55001" }
  databases:
    {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
    {  "_id" : "latis",  "partitioned" : true,  "primary" : "elastic" }
        latis.users
            shard key: { "index" : 1 }
            chunks:
                shard0000    4
                elastic    5
            { "index" : { $minKey : 1 } } -->> { "index" : 1 } on : shard0000 Timestamp(50001
            { "index" : 1 } -->> { "index" : 4369 } on : shard0000 Timestamp(30000
            { "index" : 4369 } -->> { "index" : 6554 } on : elastic Timestamp(40001
            { "index" : 6554 } -->> { "index" : 8739 } on : elastic Timestamp(10004
            { "index" : 8739 } -->> { "index" : 10923 } on : elastic Timestamp(30002
            { "index" : 10923 } -->> { "index" : 14000 } on : elastic Timestamp(30003
            { "index" : 14000 } -->> { "index" : 16184 } on : shard0000 Timestamp(40002
            { "index" : 16184 } -->> { "index" : 19000 } on : shard0000 Timestamp(40003
            { "index" : 19000 } -->> { "index" : { $maxKey : 1 } } on : elastic Timestamp(50000
    {  "_id" : "users",  "partitioned" : true,  "primary" : "elastic" }
    {  "_id" : "db",  "partitioned" : false,  "primary" : "elastic" }
    {  "_id" : "test",  "partitioned" : false,  "primary" : "elastic" }
 
 
cs


오오오오... 잘된다. 다음은 aggregation 및 mapreduce로.... 

posted by 제스트
:
개발관련/MongoDB 2015. 11. 19. 18:55

mongodb의 cluster의 최종편.... 후 힘드네.... 


mongos 이름하여 mongo cluster server 라 한다. 거두 절미 하고 셋팅 파일 부터 보자.. 

머 기존꺼랑 비슷하다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#yml 파일이 존재 하지 않으면 /var/local/mongdb/data 에 data를 저장. (경로도 마찬가지로 없으면 default 경로에 저장.)
#log역시 설정 정보가  없으면 /var/local/mongdb/logs/log.log에 저장.  
#net - network 설정
#하위 구조로 bindIp와 port를 설정한다. 
#bindIP는 mongoDB 자신의 ip를 설정. 
#port는 mongDB 의 port를 설정. 
net:
 bindIp: "192.168.0.105"
 port: 45005
#processManagement - 실행 옵션. 
#fork 는 백그라운드 옵션. 
processManagement:
 fork: true
#storage - data 저장 경로를 설정. 
#dbpath - data를 저장할 실제 경로. 
#journal - data를 쓰기 전 , data write query를 파일에 저장하는 옵션. (일종의 검증, 복구를 위한 작업인듯...) 
# enabled - journal 을 쓸지 말지의 설정.
#storage:
# dbPath: /home/solrslave/src/mongodb-linux-x86_64-rhel62-3.0.4/cluster
# journal:
#   enabled: true
 
#destination: file, syslog 2가지 옵션 사용 가능
#file로 선언하면 path 옵션을 필수로 넣어서 경로를 직접 설정
#syslog로 선언하면 경로 설정 없이 디폴트 로그파일에 저장
#
#verbosity: 로그 기록 레벨
default : 0
0 ~ 5 숫자 값으로 레벨 구분
0 : all
1 : debug,
2: information
3: warning
4: errorm
5: fatal
systemLog:
 verbosity: 1
 destination: file
 logAppend: true
 path: /home/solrslave/src/mongodb-linux-x86_64-rhel62-3.0.4/cluster_logs/cluster_log.log
 
 
sharding:
  configDB: "192.168.0.105:45004"
  chunkSize: "64"
 
cs


이것도 마지막 부분만 틀리다 sharding 이라는 설정 값이 추가 됬다 . 일단 옵션은 보통 한개면 될듯 보인다. configDB라는 옵션만..... 

configDB는 앞서 설명한 config server의 아이피와 포트가 온다. 필자는 한개만 썻지만 여러개 썻다면 "xxx.xxx.xxx.xxx:12345, xxx.xxx.xxx.xxx:23456" 요렇게 하면된다. 그리고 두번째 chunkSize라는 넘이 있다. default는 64이다. mongodb의 chunk 는 데이터의 크기의 묶음(?) 정도가 되겠다. 

이 말은 위에 구성은 여러개의 shard는 대략 저 크기로 데이터를 나눈다. 64M 이하인 data는 특정 shard 한군데를 정해서 데이터를 쌓을 것이다. 


실행은 mongd가 아닌 mongos로 실행한다. 실행후 process를 확인해보자. 

1
2
3
4
 
 
500      17431     1  0 Nov19 ?        00:01:45 ./bin/mongos -f cluster.yml
 
cs


자 이제 모든 환경 셋팅은 끝났다.  근데 이상한게 보일 것이다. replicaset과 연동은????


이제 mongos 인 cluster server에 접속하자. 접속은 기존과 동일하게 ip와 port만 cluster server로 하면된다. 


1
2
3
4
5
6
7
 
 
sh.enableSharding("testDB");//없으면 만든다.
 
sh.addShard("192.168.0.105:45001");  
 
sh.status(); 
cs


접속후 sharding과 관련된 명령어인 sh 로 먼저 어떤 db를 sharding을 할지 설정한다. 


addShard 명령어로 셋팅을 한다. 재미난 점은 위 예시는 primary 로 잡혀있는 서버를 했지만 secondary로 해도 된다. 


그럼 제대로 shard를 하기 위해서 독립서버 55001을 한개 띄우고 

sh.addShard("192.168.0.105:55001");


추가한다. 마지막으로 sh.status()로 상태 정보  를 확인해보자 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
--- Sharding Status --- 
  sharding version: {
    "_id" : 1,
    "minCompatibleVersion" : 5,
    "currentVersion" : 6,
    "clusterId" : ObjectId("564aff51f77bed76dca6ba70")
}
  shards:
    {  "_id" : "elastic",  "host" : "elastic/192.168.0.105:45001,192.168.0.105:45002,192.168.0.105:45003" }
    {  "_id" : "shard0000",  "host" : "192.168.0.105:55001" }
  databases:
    {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
    {  "_id" : "latis",  "partitioned" : true,  "primary" : "elastic" }
        latis.users
            shard key: { "index" : 1 }
            chunks:
                shard0000    4
                elastic    5
            { "index" : { $minKey : 1 } } -->> { "index" : 1 } on : shard0000 Timestamp(50001
            { "index" : 1 } -->> { "index" : 4369 } on : shard0000 Timestamp(30000
            { "index" : 4369 } -->> { "index" : 6554 } on : elastic Timestamp(40001
            { "index" : 6554 } -->> { "index" : 8739 } on : elastic Timestamp(10004
            { "index" : 8739 } -->> { "index" : 10923 } on : elastic Timestamp(30002
            { "index" : 10923 } -->> { "index" : 14000 } on : elastic Timestamp(30003
            { "index" : 14000 } -->> { "index" : 16184 } on : shard0000 Timestamp(40002
            { "index" : 16184 } -->> { "index" : 19000 } on : shard0000 Timestamp(40003
            { "index" : 19000 } -->> { "index" : { $maxKey : 1 } } on : elastic Timestamp(50000
    {  "_id" : "users",  "partitioned" : true,  "primary" : "elastic" }
    {  "_id" : "db",  "partitioned" : false,  "primary" : "elastic" }
    {  "_id" : "test",  "partitioned" : false,  "primary" : "elastic" }
 
 
 
cs


필자는 현재 data를 넣어봐서 위와 같은 그림이 보인다. 


shards:
    {  "_id" : "elastic",  "host" : "elastic/192.168.0.105:45001,192.168.0.105:45002,192.168.0.105:45003" }
    {  "_id" : "shard0000",  "host" : "192.168.0.105:55001" }


중요한 것은 위에 shards이다. 추가한 아이피와 포트가 다 생성 되있다... 

이상으로 cluster는 완성 되었다. 


다음은 cloud의 꽃(?)이라 불리는 aggregation과 mapreduce를 ...... 

posted by 제스트
:
개발관련/MongoDB 2015. 11. 19. 18:15

이번에는 replicaset에 대해 설정해보자. 먼저 단일 서버를 셋팅한 yml 파일을 복사후 replication name을 셋팅하면 된다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#yml 파일이 존재 하지 않으면 /var/local/mongdb/data 에 data를 저장. (경로도 마찬가지로 없으면 default 경로에 저장.)
#log역시 설정 정보가  없으면 /var/local/mongdb/logs/log.log에 저장.  
#net - network 설정
#하위 구조로 bindIp와 port를 설정한다. 
#bindIP는 mongoDB 자신의 ip를 설정. 
#port는 mongDB 의 port를 설정. 
net:
 bindIp: "192.168.0.105"
 port: 45001
#processManagement - 실행 옵션. 
#fork 는 백그라운드 옵션. 
processManagement:
 fork: true
#storage - data 저장 경로를 설정. 
#dbpath - data를 저장할 실제 경로. 
#journal - data를 쓰기 전 , data write query를 파일에 저장하는 옵션. (일종의 검증, 복구를 위한 작업인듯...) 
# enabled - journal 을 쓸지 말지의 설정.
storage:
 dbPath: /home/solrslave/src/mongodb-linux-x86_64-rhel62-3.0.4/data2
 journal:
   enabled: true
 
#destination: file, syslog 2가지 옵션 사용 가능
#file로 선언하면 path 옵션을 필수로 넣어서 경로를 직접 설정
#syslog로 선언하면 경로 설정 없이 디폴트 로그파일에 저장
#
#verbosity: 로그 기록 레벨
# default : 0
# 0 ~ 5 숫자 값으로 레벨 구분
# 0 : all
# 1 : debug,
# 2: information
# 3: warning
# 4: errorm
# 5: fatal
systemLog:
 verbosity: 1
 destination: file
 logAppend: true
 path: /home/solrslave/src/mongodb-linux-x86_64-rhel62-3.0.4/logs2/repl_log1.log
 
 
replication:
 replSetName: elastic
cs


replication 이름을 추가할 replica에 동일하게 써준다. 이휴 bindIp와 port를 각 서버에 맞게 셋팅한다. 필자는 centos 환경에 3개의 서버를 먼저 띄었다. 

설치된 경로에 mongod -f 설정파일.yml 을 하면 된다. 
이후 ps -ef | grep mongod 를 하면 아래와 같은 결과를 볼수 있다.

1
2
3
500      12235     1  0 Nov17 ?        00:07:42 ./bin/mongod -f startup2.yml
500      12251     1  0 Nov17 ?        00:07:05 ./bin/mongod -f startup3.yml
500      12267     1  0 Nov17 ?        00:07:03 ./bin/mongod -f startup4.yml
cs

그럼 위에 서버들이 replicaset으로 제대로 셋팅이 되었는지 확인해보자. 

아무 몽고 서버에 먼저 접속을 한다. (robomngo tool 추천 또는 ./bin/mongo 아이피:포트 로 접속 하면된다.)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use dbaname //사용할 db로 이동.
show dbs //모든 db의 이름 확인
show collections //모든 collection 이름 정보 확인
 
 
 
rs.status();
/* 1 */
{
    "set" : "elastic",
    "date" : ISODate("2015-11-20T09:44:41.517Z"),
    "myState" : 1,
    "members" : [ 
        {
            "_id" : 1,
            "name" : "192.168.0.105:45001",
            "health" : 1.0000000000000000,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 258290,
            "optime" : Timestamp(144800611422),
            "optimeDate" : ISODate("2015-11-20T07:55:14.000Z"),
            "electionTime" : Timestamp(14479202171),
            "electionDate" : ISODate("2015-11-19T08:03:37.000Z"),
            "configVersion" : 1,
            "self" : true
        }, 
        {
            "_id" : 2,
            "name" : "192.168.0.105:45002",
            "health" : 1.0000000000000000,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 92465,
            "optime" : Timestamp(144800611422),
            "optimeDate" : ISODate("2015-11-20T07:55:14.000Z"),
            "lastHeartbeat" : ISODate("2015-11-20T09:44:40.779Z"),
            "lastHeartbeatRecv" : ISODate("2015-11-20T09:44:40.805Z"),
            "pingMs" : 0,
            "syncingTo" : "192.168.0.105:45001",
            "configVersion" : 1
        }, 
        {
            "_id" : 3,
            "name" : "192.168.0.105:45003",
            "health" : 1.0000000000000000,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 92465,
            "optime" : Timestamp(144800611422),
            "optimeDate" : ISODate("2015-11-20T07:55:14.000Z"),
            "lastHeartbeat" : ISODate("2015-11-20T09:44:40.808Z"),
            "lastHeartbeatRecv" : ISODate("2015-11-20T09:44:40.783Z"),
            "pingMs" : 0,
            "syncingTo" : "192.168.0.105:45001",
            "configVersion" : 1
        }
    ],
    "ok" : 1.0000000000000000,
    "$gleStats" : {
        "lastOpTime" : Timestamp(00),
        "electionId" : ObjectId("564d825928cf905edab537fb")
    }
}
cs


mongodb의 replication 정보는 rs 명령어로 한다. rs.status() 함수를 하면 위 정보와 같이 나온다. 여기서  누가 primary이고 secondary인지 알 수있다. 기본적으로 모든 cloud는 대장(?)을 선출하는데 mongodb는 primary라 칭한다. 설정 정보를 보고싶으면, rs.config() 를 하면된다. 


다음은 shard config server에대해 알아보겠다. 


posted by 제스트
:
개발관련/MongoDB 2015. 11. 19. 11:27

몽고 db는 아래 그림과 같은 모양으로 구성된다. 

 


(출처는 http://mobicon.tistory.com/307 이분 블로그는 볼게 많아요.) 


설명을 하자면 아마도 클라우드 환경을 지원하는 대부분의 것들이 mongodb와 유사할 것이다. (solr와 es를 좀 틀리다... =-=;;;) 

먼저 cloud는 두가지 말들이 많이 나온다. shard(파편)와 replica(복제) 이 두말이 가장 먼저 나온다. 몽고 db의 shard는 위에 그림과 같이 몽고db의 물리적 서버를 여러개 합쳐놓은 논리적 단위이다. 그럼 전체 데이터를 봤을때 샤드라고 하는 논리적 단위는 일부 만을 가지게 되고 이들이 합쳐져서 전체 데이타를 이룬다. 


 물리적 서버는 다시 노드 또는 데이터 서버 라고 칭하며, 저 노드들간의 여러개를 replicaset 이라는 이름으로 다시 집합을 이룬다. 결론은 replicaset은 흔히 말하는 replica가 된다.  replica는 들어온 데이타들을 상호간에 복제를 하게 된다. 


그럼 mongos라는 넘을 무얼까? 이넘은 클러스터 서버라는 넘이다. 유저가 쿼리를 전송을 하면 클러스터 서버는 데이터를 저장하지 않고 일종의 queue역활을 해준다. 어느 데이터를 누구한테 전할지 이러한 역활을 한다. 오른쪽 위에 보면 config servers 라는 넘이 있는데 이넘은 모든 쿼리를 저장하며 백업등을 관리한다. 이 역시 장애가 발생할 수 있으므로 여러개를 권장한다. 




posted by 제스트
: