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

2015년 3월 17일 화요일

mongodb create insert statement from collection using script

mongodb create insert statement from collection using script

yep~ i know this is a just trick but it is useful when developing system
  1. code
    var c = db.testType.find();
    while(c.hasNext()){
     var data = c.next();
     print('db.testType.insert(')
     printjson(data);
     print(');')
    }
    
  2. result
    db.testType.insert(
    { "_id" : "global", "serviceName" : "a", "url" : "global" }
    );
    db.testType.insert(
    { "_id" : "seoul", "serviceName" : "a ", "url" : "seoul" }
    );
    db.testType.insert(
    { "_id" : "jeju", "serviceName" : "a ", "url" : "jeju" }
    );
    db.testType.insert(
    { "_id" : "honkong", "serviceName" : "a ", "url" : "honkong" }
    );
    db.testType.insert(
    { "_id" : "taifei", "serviceName" : "a ", "url" : "taifei" }
    );
    db.testType.insert(
    { "_id" : "japan", "serviceName" : "a ", "url" : "japan" }
    );
    db.testType.insert(
    { "_id" : "taiwan", "serviceName" : "a ", "url" : "taiwan" }
    );
    

2015년 2월 25일 수요일

mongodb replication v2.6

         
1.디렉토리를 만든다.
   mkdir rs0
mkdir rs0/server1
mkdir rs0/server2
mkdir rs0/server3      
         
  1. cd /
  2. chown mkdir /test/
  3. sudo chown 유저이름 /test/
  4. mkdir rs0

2.몽고 디비를 뛰운다.
  1. mongod --port 27001 --dbpath /test/ --replSet 'rs0'


   port는 27001 로 생성될  디비의 경로는 /test/ 밑으로 레플리케이션 이름은 'rs0'으로

2015년 2월 16일 월요일

몽고 레플리케이션 싱크에러


몽고에러

레플리케이션이나 샤딩에러


싱크 에러

  1. 몽고에 에러가 발생했을 경우 마스터 서버로 간다.
몽고가 있는 서버로 가서
ps -ax | grep mongo
 8373 ?        Sl   608:30 /usr/bin/mongod -f /etc/mongod.conf
 8465 ?        Sl   768:49 /usr/bin/mongod -f /etc/mongod-config-server.conf
11927 pts/2    S+     0:00 grep mongo
26213 ?        Sl   852:33 /usr/bin/mongos -f /opt/thirdparty/mongos_test.conf
  1. 컨피그를 확인해서 몽고스를 통하지 않고 직접 마스터의 포트로 접속
    ps -ax | grep mongo
     port = 숫자
    
  2. 마스터에서 레플 또는 샤딩 상태를 확인
    -인증을 받고
    use admin
    db.auth(id,pw)
    rs.status()
shard-a:PRIMARY> rs.status()
{
    "set" : "shard-a",
    "date" : ISODate(""),
    "myState" : 1,
    "members" : [
        {
            "_id" : 0,
            "name" : "ip1,
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 9658337,
            "optime" : Timestamp(),
            "optimeDate" : ISODate(""),
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "ip2",
            "health" : 1,
            "state" : 3,
            "stateStr" : "RECOVERING",
            "uptime" : 720382,
            "optime" : Timestamp(),
            "optimeDate" : ISODate(""),
            "lastHeartbeat" : ISODate(""),
            "lastHeartbeatRecv" : ISODate(""),
            "pingMs" : 0,
            "lastHeartbeatMessage" : "still syncing, not yet to minValid optime 54e1c1a7:34",
            "syncingTo" : "ip1"
        },
        {
            "_id" : 2,
            "name" : "ip3",
            "health" : 1,
            "state" : 7,
            "stateStr" : "ARBITER",
            "uptime" : 720395,
            "lastHeartbeat" : ISODate(""),
            "lastHeartbeatRecv" : ISODate(""),
            "pingMs" : 0
        }
    ],
    "ok" : 1
}
  1. 문제가 있다면
  • 위의 경우는 레플리케이션에서 싱크가 되어있지 않다.
  • 해당 레플리케이션 서버로 이동
  • 1, 2번 을 적용해서 로깅 위치 확인
  • 로깅으로 가서 해당 날짜 사유 확인
  1. 싱크관련 에러
    [rsBackgroundSync] replSet syncing to: masterIP
    [rsBackgroundSync] replSet error RS102 too stale to catch up, at least from masterIP
    [rsBackgroundSync] replSet our last optime : 
    [rsBackgroundSync] replSet oldest at masterIP :
    [rsBackgroundSync] replSet See http://dochub.mongodb.org/core/resyncingaverystalereplicasetmember
    [rsBackgroundSync] replSet error RS102 too stale to catch up
    [rsBackgroundSync] replSet RECOVERING
    
  • oplog 의 사이즈를 넘어가면 위와 같은 에러가 발생한다 디폴트 사이즈는?
    디폴트 크기는 사용가능 한 디스크의 5%를 몽고 디비가 설정한다.
    권장사항은 최소 디비에 적일 양의 24시간을 버틸 정도로 설정해야 한다.
    실 어드민은 가능한 최대한 많이를 추천한다.(capped collection 이기 때문에 덥어쓰면 복구가 안되기 때문이다.)
  • 그렇다면 어디서 로그 크기를 확인하는가?
    버전 2.4 db.printSlaveReplicationInfo()
    버전 2.6 rs.printReplicationInfo()

  • 최초에 바꾸기
    replication.oplogSizeMB
  • 나중에 바꾸기
    The way the sync works is secondary notes a place in the oplog on the
    primary, then starts copying all the data over.
    http://docs.mongodb.org/manual/tutorial/change-oplog-size/
    db.runCommand( { create: “oplog.rs”, capped: true, size: (2 1024 1024 * 1024) } )

시간 에러

  1. 서버 시간이 다를 경우 mongos 에서 connection 접속시 에러가 발생할수 있다.
    ntp 를 사용해서 서버끼리 시간을 동기화 해주고 cron에 추가해서 배치잡으로 돌리자.

2015년 2월 8일 일요일

mongodb Array in array query

mongodb Array in array query

array 안에 array 가 있고 그안의 객체에 array 가 있고 거기에 val 쿼리하기
doc = {
    array1 :[
        [
            {
                array2:[{ key:'val'},{ key:'val'}]
            },
            {}    
        ],
        []
    ]
}

db.doc.find({'array1':{$elemMatch:{$elemMatch:{array2:{$elemMatch:{'key':'val'}}}}}})

2015년 2월 4일 수요일

몽고디비 오브젝트 사이즈

몽고디비 오브젝트 사이즈

평균사이즈 구하기
var tot = 0;
var cnt = 0;
db.spot.find().forEach(function(obj) {
    var curr = Object.bsonsize(obj); 
    tot += curr;
    cnt += 1;    
})
var objSizeByBite = tot / cnt;
var objSizeByMega = objSizeByBite / (1024 * 1024);
print(objSizeByMega)
주의
Object.bsonsize(db.find({_id:’A’})); 하면 안된다 커서 크기를 측정하는 같다.
Object.bsonsize(db.findOne({_id:’A’})); 해야 된다.

2014년 11월 17일 월요일

mongorestore single collection


  1. 싱글 컬랙션
    • 맨마지막에 파일까지 지정해주어야한다.
      mongorestore -d deployd -c spots spots/spots.bson
      
  2. 전체 디비
    • 디비명 폴더
      mongorestore -d deployd deployd/
      

2014년 10월 12일 일요일

몽고디비2.6 샤딩

1.0 컨피스 서버용 디렉토리 만들기
cd test
mkdir log //로그용 디렉토리
mkdir configsvr
cd configsvr/
mkdir server1
mkdir server2
  mkdir server3

1.1 컨피그 서버 뛰우기
컨피그 서버는 총 3대를 뛰운다
컨피그 서버중 1대라도 죽으면 컨피그 서버의 메타 데이터는 읽기 전용이된다.
샤딩용 데이터 목록만 저장하고 있기 때문에 많은 자원을 소모하지 않는다.
옵션 --configsvr 는 --port 27019 --dbpath /data/configdb 를 추가하는 기능만 있음
덥어 쓸수 있음

구성 서버 데이터를 자주 백업 받고 유지보수 작업시에도 반드시 데이터를 백업 받자

mongod --configsvr --dbpath /test/configsvr/server1  --logpath /test/log/config_server_1 --fork --port 28001
mongod --configsvr --dbpath /test/configsvr/server2  --logpath /test/log/config_server_2 --fork --port 28002
mongod --configsvr --dbpath /test/configsvr/server3  --logpath /test/log/config_server_3 --fork --port 28003

1.2 몽고s 뛰우기
컨피그 서버가 뜬다음에 뛰울수 있다.

mongos --configdb 127.0.0.1:28001,127.0.0.1:28002,127.0.0.1:28003 --logpath /test/log/mongos_1 --fork --port 10000

1.3 이미 있는 복제셋 추가하기
mongo --port 10000
sh.addShard('rs0/127.0.0.1:27001,127.0.0.1:27002,127.0.0.1:27003')

sh.status()
--- Sharding Status ---
 sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("543a70e0e74f6e2fe12c8638")
}
shards:
{  "_id" : "rs0",  "host" : "rs0/127.0.0.1:27001,127.0.0.1:27002,127.0.0.1:27003" }
databases:
{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
{  "_id" : "test",  "partitioned" : false,  "primary" : "rs0" }

1.4 mongos 가 뛰어 졌으면 샤드에 직접적으로 접속 하지 못하게 방화벽 규칙을 설정한다.
1.5 샤딩을 추가할떄는 빈 복제셋을 추가하면된다.
샤드 별로 다른 디비를 만들어서 추가 할수 도 있다.
이럴 경우 디비 별로 샤딩 된다.

1.6 테스트2 복제 셋을 만들어서 샤딩에 추가해보
디렉토리를 만들자
cd test
mkdir rs1
mkdir server1
mkdir server2
mkdir server3

mongod --port 29001 --dbpath /test/rs1/server1 --replSet 'rs1' --logpath /test/log/rs1_server_1 --fork
mongod --port 29002 --dbpath /test/rs1/server2 --replSet 'rs1' --logpath /test/log/rs1_server_2 --fork
mongod --port 29003 --dbpath /test/rs1/server3 --replSet 'rs1' --logpath /test/log/rs1_server_3 --fork

mongo --port 29001
var rsconfig = {"_id":"rs1", "members":[{"_id":1, "host":"127.0.0.1:29001"},{"_id":2, "host":"127.0.0.1:29002"},{"_id":3, "host":"127.0.0.1:29003"}]}

rs.initiate(rsconfig)

use test2
function insertTest(count){
for(var i = 0; i< count; i++){
db.test1.insert({a:i, b:i});
}
}

insertTest(1000);

> mongos 접속
sh.addShard('rs1/127.0.0.1:29001,127.0.0.1:29002,127.0.0.1:29003')

1.7 샤딩하기
디비를 샤딩한다.
> mongos 접속
use test
sh.enableSharding('test')db.enableSharding('test');

sh.status()
 databases:
{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
{  "_id" : "test",  "partitioned" : true,  "primary" : "rs0" }
{  "_id" : "test2",  "partitioned" : false,  "primary" : "rs1" }

partitioned true 확인

1.8 컬랙션 샤딩하기
db.test1.ensureIndex({a:1})
샤딩 키에 인덱스가 없으면 에러가 발생한다.
sh.shardCollection('test.test1',{a:1})

function insertTest(count){
for(var i = 0; i< count; i++){
db.test1.insert({a:i, b:i});
}
}

insertTest(10000);
sh.status()
databases:
{  "_id" : "test",  "partitioned" : true,  "primary" : "rs0" }
test.test1
shard key: { "a" : 1 }
chunks:
rs1 1
rs0 1
{ "a" : { "$minKey" : 1 } } -->> { "a" : 0 } on : rs1 Timestamp(2, 0)
{ "a" : 0 } -->> { "a" : { "$maxKey" : 1 } } on : rs0 Timestamp(2, 1)
아래와 같이 청크가 샤딩 된걸 확일 할수 있다.





몽고디비2.6 리플리케이션

1.테스트용 디렉토리 만들기
1.1 컨피그 디렉토리 만들기
cd /
sudo mkdir /cofig
sudo chown lee /config

1.2 테스트 디비용 디렉토리 만들기
cd /
sudo mkdir /test
sudo chown lee /test
cd mkdir rs0

mkdir rs0
mkdir rs0/server1
mkdir rs0/server2
mkdir rs0/server3

1.3 레플리케이션 시작하기
mongod --port 27001 --dbpath /test/rs0/server1 --replSet 'rs0' --logpath /test/log/rs0_server_1 --fork
mongod --port 27002 --dbpath /test/rs0/server2 --replSet 'rs0' --logpath /test/log/rs0_server_2 --fork
mongod --port 27003 --dbpath /test/rs0/server3 --replSet 'rs0' --logpath /test/log/rs0_server_3 --fork

옵션 설명
--port
디비가 시작할 포트
--dbpath
디비가 위치할 디렉토리
--replSert
레플리케이션 이름
1.4 레플리케이션 설정하기
몽고 쉘로 접속해서 최초 레플리케이션을 init 한다.

mongo --port 27001
var rsconfig = {"_id":"rs0", "members":[{"_id":1, "host":"127.0.0.1:27001"}]}

rs.initiate(rsconfig)

*테스트를 위해 localhost ,127.0.0.1 을 지원하지만 다른 ip 와 섞어 쓰는건 안된다.

1.5 복제셋 맴버추가
rs.add("127.0.0.1:27002")
rs.add("127.0.0.1:27003")

1.6 복제셋 멤버제거
/*
rs.remove("127.0.0.1:27002")
*/

1.7 복세셋 멤버 확인
rs.config()
{
"_id" : "rs0",
"version" : 5,
"members" : [
{
"_id" : 1,
"host" : "127.0.0.1:27001"
},
{
"_id" : 3,
"host" : "127.0.0.1:27003"
},
{
"_id" : 4,
"host" : "127.0.0.1:27002"
}
]
}

_id : 복제셋 이름
verstion : 멤버를 추가할때마다

1.8 컨피그 변경이 가능함
/*
var reconfig = rs.config()
reconfig.members[1].host = '0.0.0.0:27003';
rs.reconfig(reconfig)
*/

1.9 세컨더리 접속
mongo --port 27002

2.레플리케이션 상태 확인

2.0 마스터에서 확인
mongo --port 27001
db.isMaster()
{
"setName" : "rs0",
"setVersion" : 5,
"ismaster" : true,
"hosts" : [
"127.0.0.1:27001",
"127.0.0.1:27002",
"127.0.0.1:27003"
],
"primary" : "127.0.0.1:27001",
"me" : "127.0.0.1:27001",
"localTime" : ISODate("2014-10-10T14:59:32.981Z"),
"maxWireVersion" : 2,
"minWireVersion" : 0,
"ok" : 1
}

2.1 마스터 : 예제 컬랙션 insert
use test

function insertTest(count){
for(var i = 0; i< count; i++){
db.test1.insert({a:i, b:i});
}
}

insertTest(1000);
db.test1.find();

2.2 마스터 : 레플리케이션 상태확인
rs.status()

*실제로 레플리케이션에 모든 복제가 완료 되었는지 확인하려면
optimeDate 가 동일한지 확인하면 된다.
{
"set" : "rs0",
"date" : ISODate("2014-10-10T15:04:57Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "127.0.0.1:27001",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 2331,
"optime" : Timestamp(1412953460, 1000),
"optimeDate" : ISODate("2014-10-10T15:04:20Z"),
"electionTime" : Timestamp(1412951411, 1),
"electionDate" : ISODate("2014-10-10T14:30:11Z"),
"self" : true
},
{
"_id" : 3,
"name" : "127.0.0.1:27003",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 924,
"optime" : Timestamp(1412953460, 1000),
"optimeDate" : ISODate("2014-10-10T15:04:20Z"),
"lastHeartbeat" : ISODate("2014-10-10T15:04:55Z"),
"lastHeartbeatRecv" : ISODate("2014-10-10T15:04:56Z"),
"pingMs" : 0,
"syncingTo" : "127.0.0.1:27001"
},
{
"_id" : 4,
"name" : "127.0.0.1:27002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 893,
"optime" : Timestamp(1412953460, 1000),
"optimeDate" : ISODate("2014-10-10T15:04:20Z"),
"lastHeartbeat" : ISODate("2014-10-10T15:04:56Z"),
"lastHeartbeatRecv" : ISODate("2014-10-10T15:04:56Z"),
"pingMs" : 0,
"syncingTo" : "127.0.0.1:27001"
}
],
"ok" : 1
}

2.3 슬레이브 : 읽기 시도
db.test1.find()
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }

몽고 디비에서 레플리케이션 셋의 기본 설정은 슬레이브에서 읽는게 안된다.
(슬레이브에서 읽을 경우 예전 데이터를 읽을수 있기 때문에)

어플리케이션에서 예전 데이터를 읽어도 상관없을때는
마스터 > rs.slaveOk()
슬레이브 읽기가 허용된다.

슬레이브 > db.test1.find(); 결과값이 리턴된다.

2.4 디비가 죽을 경우의 마스터 선출 작업
27001 디비를 죽인다. ctrl+c

슬레이브1 > rs.status()
현재 마스터 이며 member 의 27001 이 죽었음을 확인한다.
27001
"health" : 0,

mongod --port 27001 --dbpath /test/rs0/server1 --replSet 'rs0'
다시 시작한다.

슬레이브1 > rs.status()
좀전의 27001 이 정상동작 하는지 확인
27001
"health" : 1,

* 3 대중 2대가 살아 남을 경우 투표를 통해 하나의 슬레이브를 마스터로 승격 시킨다.
투표를 하기위해서는 과반수가 살아 있어야 한다.
ex)3 대 이면 2대, 4 대이면 3대 ...

* 과반수가 살아 있지 않는다면 투표를 할수 없기 때문에 secondery 상태가 유지된다.
why? 과반수 인가?
a, b 데이터 센터에 몽고디비 1,2,3을 배치했다
현재 마스터는 a:1 이다.
a : 1,2
b : 3

b 데이터 센터가 일시적으로 네트워크가 단절되었다
과반수가 아니라면 b: 3이 마스터가 되고 데이터를 받아드린다.
이때 a:1 도 마스터이기 때문에 네트워크가 복구 되면 데이터의 정합성 문제가 발행한다.

2.5 세컨더리에서 프라이머리로 변경하기
(3개의 멤버 중에서 2개의 맴버가 죽었다고 가정 살아있는 맴버를 프라이머리로 만들기)
var cfg = rs.config()
rs0:SECONDARY> cfg
{
"_id" : "rs0",
"version" : 5,
"members" : [
{
"_id" : 1,
"host" : "127.0.0.1:27001"
},
{
"_id" : 3,
"host" : "127.0.0.1:27003"
},
{
"_id" : 4,
"host" : "127.0.0.1:27002"
}
]
}

27001 이 세건더리이고 27002, 27003 이 죽었을 경우
cfg.members = [cfg.members[0]]
cfg 로 멤버 확인
{
"_id" : "rs0",
"version" : 5,
"members" : [
{
"_id" : 1,
"host" : "127.0.0.1:27001"
}
]
}

rs.reconfig(cfg, {force : true})
rs.status()
현재 서버가 프라이머리인거 확인




2.6 아비타 더하기
cd /test
mkdir rs0/arb1

mongod --port 27004 --dbpath /test/rs0/arb1 --replest rs0
프라이머리 : rs.addArb('127.0.0.1:27004')

rs.status()
{
"set" : "rs0",
"date" : ISODate("2014-10-12T06:49:55Z"),
"myState" : 1,
"members" : [
{
"_id" : 1,
"name" : "127.0.0.1:27001",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1095,
"optime" : Timestamp(1413096584, 1),
"optimeDate" : ISODate("2014-10-12T06:49:44Z"),
"electionTime" : Timestamp(1413096488, 1),
"electionDate" : ISODate("2014-10-12T06:48:08Z"),
"self" : true
},
{
"_id" : 2,
"name" : "127.0.0.1:27004",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 11,
"lastHeartbeat" : ISODate("2014-10-12T06:49:54Z"),
"lastHeartbeatRecv" : ISODate("2014-10-12T06:49:55Z"),
"pingMs" : 0
}
],
"ok" : 1
}

stateStr 'ARBITER' 확인

2.7 아비터가 실제 동작하는지 또한 실제로 데이터는 없는지 확인
mongo --prot 27004
show dbs
테스트 db가 없는지 확인

use test
test.test1.insert({a:1})

하게 되면 에러가 발생하면서 인설트 되지 않는게 맞다

2.8 프라이머리를 죽였을때 아비터가 실제로 투표에 참여하는지 확인
27001 을 죽인다.
mongo --port 27002
에서 secondery 에서 primary 로 변경 되었는지 확인

2.9 우선 순위로 프라이머리로 설정 하고 싶은 마스터를 설정하기
기본적으로 priority 1 높으면 높을 수록 우선 순위를 가진다.
만약 priority 를 0 으로 하면 해당 멤버는 절대 primary 가 될수 없다.

rs.add({_id:4, host:"127.0.0.1:27003", priority:1.5})

접속 되있던 창은 primary -> secnodery 가 되고
mongo --port 27003으로 접속하면 우선 순위가 높은 애가 프라이머리가 되어 있다.

우선 순위는 rs.config() 에서 확인 가능 하다
{
"_id" : "rs0",
"version" : 25498,
"members" : [
{
"_id" : 1,
"host" : "127.0.0.1:27001"
},
{
"_id" : 2,
"host" : "127.0.0.1:27004",
"arbiterOnly" : true
},
{
"_id" : 3,
"host" : "127.0.0.1:27002"
},
{
"_id" : 4,
"host" : "127.0.0.1:27003",
"priority" : 1.5
}
]
}

이번에는 더하지않고 그냥 프라이머리를 바꿔만 보자
var cfg = rs.config()
cfg.members[0].priority = 2
rs.reconfig(cfg)

mongo --port 27001
프라이머리 확인

3.0 멤버 숨기기
클라이언트에 보이기 싫은 멤버는 아래와 같이 hidden 과 priority 를
조절해서 안보이게 할 수 있다.

var cfg = rs.config()
config.members[1].hidden = 0
config.members[1].priority = 0
rs.recofig(cfg)

rs.isMaster() 에서 사라지게 된다.
클라이언트는 isMaster() 를 호출해서 복제 셋의 멤버를 확인 하기 때문에
해당 부분만 고치면된다.

보이게 할려면 해당 속성 삭제하고 리컨피그 하면된다.

3.1 슬레이브 지연
컨피그에 아래 두개의 속성 추가
slaveDelay = 60 * 60 *24 (하루)
priority = 0

3.2 인덱스 생성안하기
인덱스를 생성하지 않는다.

buildIndexes = false
priority = 0