4일차 교육 |
1. 샤딩 시스템의 문제점
- 청크 사이즈 - 사이즈가 작으면 청크 마이그레이션 횟수가 증가
- 샤드 키 - 분포도가 좋은 필드로 지정하는 것이 가장 적합하다.
- hashed sharding -> 일반필드를 지정하면 해시값으로 키를 생성. db.컬렉션.ensureIndex({ a : "hashed "})
- 청크 사이즈 - 사이즈가 작으면 청크 마이그레이션 횟수가 증가
- 샤드 키 - 분포도가 좋은 필드로 지정하는 것이 가장 적합하다.
- hashed sharding -> 일반필드를 지정하면 해시값으로 키를 생성. db.컬렉션.ensureIndex({ a : "hashed "})
2. Replica & ReplicaSets
1) Master & slave
- 마스터가 메인, 마스터의 데이터를 슬래이브(s)로 복제. 슬레이브는 최대 32개 가능.
- 마스터에 문제가 발생할 경우 슬래이브를 마스터로 수정해줘야함. 슬레이브가 메인이 될 경우 Read-only.
- 마스터가 메인, 마스터의 데이터를 슬래이브(s)로 복제. 슬레이브는 최대 32개 가능.
- 마스터에 문제가 발생할 경우 슬래이브를 마스터로 수정해줘야함. 슬레이브가 메인이 될 경우 Read-only.
(실습)
- 폴더 3개 생성. master, slave1, slave2
- mongod --dbpath c:\mongodb\master\ --port 10000 --master
- mongod --dbpath c:\mongodb\slave1\ --port 10001 --slave --source localhost:10000
- mongod --dbpath c:\mongodb\slave2\ --port 10002 --slave --source localhost:10000
- 세군데 모두 접속
- mongo localhost:10000, mongo localhost:10001, mongo localhost:10002
- 마스터에서 insert명령
- db.things.insert({ a : 1}) // 마스터에 insert, 슬레이브에 자동으로 복제
- 세군데에서 find 명령
- db.things.find()
- 슬레이브2 서버 셧다운, 해당 폴더 비우기
- use admin
- db.shutdownServer()
- slave2 폴더 내용 삭제
- 셧다운된 도스창을 확인후 다시실행
- slave2 폴더 내용 확인 // 자동 복구됨. 마스터의 경우에는 직접 복구해야함.
- db.things.insert({ b : 3})
- 이번엔 마스터를 셧다운 후 해당 폴더 삭제
- 슬레이브 모두 셧다운
- 슬레이브 파일을 마스터쪽으로 복사
- --autoresync 옵션을 주어 싱크가 되도록 다시 구동
- mongod --dbpath c:\mongodb\master\ --port 10000 --master --autoresync
- mongod --dbpath c:\mongodb\slave1\ --port 10001 --slave --source localhost:10000 --autoresync
- mongod --dbpath c:\mongodb\slave2\ --port 10002 --slave --source localhost:10000 --autoresync
- find 명령으로 모두 확인.
- 폴더 3개 생성. master, slave1, slave2
- mongod --dbpath c:\mongodb\master\ --port 10000 --master
- mongod --dbpath c:\mongodb\slave1\ --port 10001 --slave --source localhost:10000
- mongod --dbpath c:\mongodb\slave2\ --port 10002 --slave --source localhost:10000
- 세군데 모두 접속
- mongo localhost:10000, mongo localhost:10001, mongo localhost:10002
- 마스터에서 insert명령
- db.things.insert({ a : 1}) // 마스터에 insert, 슬레이브에 자동으로 복제
- 세군데에서 find 명령
- db.things.find()
- 슬레이브2 서버 셧다운, 해당 폴더 비우기
- use admin
- db.shutdownServer()
- slave2 폴더 내용 삭제
- 셧다운된 도스창을 확인후 다시실행
- slave2 폴더 내용 확인 // 자동 복구됨. 마스터의 경우에는 직접 복구해야함.
- db.things.insert({ b : 3})
- 이번엔 마스터를 셧다운 후 해당 폴더 삭제
- 슬레이브 모두 셧다운
- 슬레이브 파일을 마스터쪽으로 복사
- --autoresync 옵션을 주어 싱크가 되도록 다시 구동
- mongod --dbpath c:\mongodb\master\ --port 10000 --master --autoresync
- mongod --dbpath c:\mongodb\slave1\ --port 10001 --slave --source localhost:10000 --autoresync
- mongod --dbpath c:\mongodb\slave2\ --port 10002 --slave --source localhost:10000 --autoresync
- find 명령으로 모두 확인.
2) ReplicaSets
- Primary server와 Secondary(s)서버. Primary에 문제가 발생할 경우 secondary가 자동으로 메인이 된다.
- Primary에 쌓인 데이터는 opLog에 우선 백업 후 Secondary 서버로 복제된다. 이는 복제가 실패할 경우를 위함이다.
- Heartbeat : 매 2초마다 상대 서버의 상태를 체크
- Primary server와 Secondary(s)서버. Primary에 문제가 발생할 경우 secondary가 자동으로 메인이 된다.
- Primary에 쌓인 데이터는 opLog에 우선 백업 후 Secondary 서버로 복제된다. 이는 복제가 실패할 경우를 위함이다.
- Heartbeat : 매 2초마다 상대 서버의 상태를 체크
- Primary server 선출방법
a) Priority에 의한 선출. 사용자가 우선순위를 주어 다음 Primary를 지정.
b) Arbiter 서버에 의한 선출. 아비터 서버는 사양이 좋을 필요는 없다.
a) Priority에 의한 선출. 사용자가 우선순위를 주어 다음 Primary를 지정.
b) Arbiter 서버에 의한 선출. 아비터 서버는 사양이 좋을 필요는 없다.
- 멤버의 종류
a) Secondary only member - 복제후 read only 셀렉트만 하는 역할.
b) hidden member - 아비터가 Primary 서버로 선택하지 못하게 하는 옵션
c) Arbiter member - 장애발생시 Primary 서버 선출역할만 진행.
d) Delayed member - Secondary 옵션으로 데이터복제가 실시간이 아니라 딜레이 시간이 지난뒤 복제되도록 설정
e) non voting member - Secondary only member 와 같은 개념. Primary 서버로 선택받지 않는 옵션.
a) Secondary only member - 복제후 read only 셀렉트만 하는 역할.
b) hidden member - 아비터가 Primary 서버로 선택하지 못하게 하는 옵션
c) Arbiter member - 장애발생시 Primary 서버 선출역할만 진행.
d) Delayed member - Secondary 옵션으로 데이터복제가 실시간이 아니라 딜레이 시간이 지난뒤 복제되도록 설정
e) non voting member - Secondary only member 와 같은 개념. Primary 서버로 선택받지 않는 옵션.
(실습)
- 폴더 4개 생성. disk1, disk2, disk3, arbiter
- mongod --dbpath c:\mongodb\disk1\ --port 10001 --replSet rptmongo --oplogSize 10 --rest //replSet의 이름을 rptmongo라고 지정.
- mongod --dbpath c:\mongodb\disk2\ --port 10002 --replSet rptmongo --oplogSize 10 --rest //oplogSize 사이즈는 10MB로 지정
- mongod --dbpath c:\mongodb\disk3\ --port 10003 --replSet rptmongo --oplogSize 10 --rest
- mongod --dbpath c:\mongodb\arbiter\ --port 10004 --replSet rptmongo --oplogSize 10 --rest //아비터 서버
- admin으로 접속
- mongo localhost:10001/admin
- 리플리카셋 init
- db.runCommand({"replSetInitiate" : {"_id" : "rptmongo", "members" :
[{"_id" : 1, "host" : "localhost:10001"},
{"_id" : 2, "host" : "localhost:10003"},
{"_id" : 3, "host" : "localhost:10002"},
{"_id" : 4, "host" : "localhost:10004", arbiterOnly:true}]
}})
- 상태 확인
- db.printReplicationInfo()
- 프롬프트 변경
- use test
- db.things.insert({a:1}) //Secondary에도 복제
- mongo localhost:10002/admin //Secondary 서버 접속
- use test
- db.getMongo().setSlaveOk() //이 명령을 실행해야 Secondary에서도 find를 할 수 있음.
- db.things.find() // 확인
- db.things.insert({b:3}) //불가능함.
-> Primary 서버 셧다운(장애발생)
- use admin, db.shutdownServer()
- Secondary 서버 둘 중 하나가 Primary로 자동 변환. 프롬프트로 확인.
- 셧다운된 서버를 재구동
- 프롬프트를 확인해보면 Secondary가 되어있음.
- Secondary 둘 다 셧다운 할 경우 Primary는 Secondary로 변경됨. 운영 불가하다는 의미.
-> 아비터는 find 명령을 해봐도 데이터 없음
- 아비터를 셧다운 한 뒤 Primary에 장애가 발생하면 나머지 두 서버는 그대로 Secondary
-> 서버 한대 더 생성
- mongod --dbpath c:\mongodb\disk4\ --port 10005 --replSet rptmongo --oplogSize 10 --rest
- Primary에서 새로 생성된 서버를 add
- rs.add("localhost:10005")
- 상태확인 => db.printSlaveReplicationInfo() 또는 rs.status()
- db.getMongo().setSlaveOk() 및 find()
- 서버를 제거
- rs.remove("localhost:10005") => 내 경우 Primary가 변경됨.
-> oplog 용량 변경
- mongodump --db local --collection 'oplog.rs' --port 10001
- mongo --port 10001
- use local
- db.temp.save(db.oplog.rs.find().sort({$natural : -1}).limit(1).next()) //oplog 내용을 temp에 save. 이 코딩이 맞는지는 확인해봐야겠다.
- db.temp.find() // 확인
- db.oplog.rs.drop() //oplog 영역 제거
- db.runCommand( {create:"oplog.rs", capped:true, size:20000000} ) //20MB로 다시 생성
- db.oplog.rs.save(db.temp.findOnd()) //temp 컬렉션에 있는 복사본을 복제
- 폴더 4개 생성. disk1, disk2, disk3, arbiter
- mongod --dbpath c:\mongodb\disk1\ --port 10001 --replSet rptmongo --oplogSize 10 --rest //replSet의 이름을 rptmongo라고 지정.
- mongod --dbpath c:\mongodb\disk2\ --port 10002 --replSet rptmongo --oplogSize 10 --rest //oplogSize 사이즈는 10MB로 지정
- mongod --dbpath c:\mongodb\disk3\ --port 10003 --replSet rptmongo --oplogSize 10 --rest
- mongod --dbpath c:\mongodb\arbiter\ --port 10004 --replSet rptmongo --oplogSize 10 --rest //아비터 서버
- admin으로 접속
- mongo localhost:10001/admin
- 리플리카셋 init
- db.runCommand({"replSetInitiate" : {"_id" : "rptmongo", "members" :
[{"_id" : 1, "host" : "localhost:10001"},
{"_id" : 2, "host" : "localhost:10003"},
{"_id" : 3, "host" : "localhost:10002"},
{"_id" : 4, "host" : "localhost:10004", arbiterOnly:true}]
}})
- 상태 확인
- db.printReplicationInfo()
- 프롬프트 변경
- use test
- db.things.insert({a:1}) //Secondary에도 복제
- mongo localhost:10002/admin //Secondary 서버 접속
- use test
- db.getMongo().setSlaveOk() //이 명령을 실행해야 Secondary에서도 find를 할 수 있음.
- db.things.find() // 확인
- db.things.insert({b:3}) //불가능함.
-> Primary 서버 셧다운(장애발생)
- use admin, db.shutdownServer()
- Secondary 서버 둘 중 하나가 Primary로 자동 변환. 프롬프트로 확인.
- 셧다운된 서버를 재구동
- 프롬프트를 확인해보면 Secondary가 되어있음.
- Secondary 둘 다 셧다운 할 경우 Primary는 Secondary로 변경됨. 운영 불가하다는 의미.
-> 아비터는 find 명령을 해봐도 데이터 없음
- 아비터를 셧다운 한 뒤 Primary에 장애가 발생하면 나머지 두 서버는 그대로 Secondary
-> 서버 한대 더 생성
- mongod --dbpath c:\mongodb\disk4\ --port 10005 --replSet rptmongo --oplogSize 10 --rest
- Primary에서 새로 생성된 서버를 add
- rs.add("localhost:10005")
- 상태확인 => db.printSlaveReplicationInfo() 또는 rs.status()
- db.getMongo().setSlaveOk() 및 find()
- 서버를 제거
- rs.remove("localhost:10005") => 내 경우 Primary가 변경됨.
-> oplog 용량 변경
- mongodump --db local --collection 'oplog.rs' --port 10001
- mongo --port 10001
- use local
- db.temp.save(db.oplog.rs.find().sort({$natural : -1}).limit(1).next()) //oplog 내용을 temp에 save. 이 코딩이 맞는지는 확인해봐야겠다.
- db.temp.find() // 확인
- db.oplog.rs.drop() //oplog 영역 제거
- db.runCommand( {create:"oplog.rs", capped:true, size:20000000} ) //20MB로 다시 생성
- db.oplog.rs.save(db.temp.findOnd()) //temp 컬렉션에 있는 복사본을 복제
(복합실습)
mongod --dbpath c:\mongodb\DATA\SHARD_B\ --port 40002 --replSet blue --oplogSize 10 --rest
mongod --configsvr --dbpath c:\mongodb\DATA\CONFIG_A4 --port 30004
mongod --dbpath c:\mongodb\DATA\S_B1\ --port 50002 --replSet blue --oplogSize 10 --rest
mongod --dbpath c:\mongodb\DATA\S_A2\ --port 60001 --replSet red --oplogSize 10 --rest
(initiate 실습)
-- 4개 띄우기
mongod --dbpath c:\mongodb\TE\Primary\ --port 15001 --replSet rptmongo --oplogSize 10 --rest
mongod --dbpath c:\mongodb\TE\Secondary1\ --port 15002 --replSet rptmongo --oplogSize 10 --rest
mongod --dbpath c:\mongodb\TE\Secondary2\ --port 15003 --replSet rptmongo --oplogSize 10 --rest
mongod --dbpath c:\mongodb\TE\hidden\ --port 15004 --replSet rptmongo --oplogSize 10 --rest
mongod --dbpath c:\mongodb\TE\Secondary1\ --port 15002 --replSet rptmongo --oplogSize 10 --rest
mongod --dbpath c:\mongodb\TE\Secondary2\ --port 15003 --replSet rptmongo --oplogSize 10 --rest
mongod --dbpath c:\mongodb\TE\hidden\ --port 15004 --replSet rptmongo --oplogSize 10 --rest
-- 15001 서버로 접근. -> mongo localhost:15001
conf = {
_id:"rptmongo",
members:[
{_id:0, host:"localhost:15001", priority:3},
{_id:1, host:"localhost:15002", priority:1},
{_id:2, host:"localhost:15003", priority:2},
{_id:3, host:"localhost:15004", priority:0, hidden:true, slaveDelay:1800}
]
}
_id:"rptmongo",
members:[
{_id:0, host:"localhost:15001", priority:3},
{_id:1, host:"localhost:15002", priority:1},
{_id:2, host:"localhost:15003", priority:2},
{_id:3, host:"localhost:15004", priority:0, hidden:true, slaveDelay:1800}
]
}
rs.initiate(conf) ==> 리플리카셋 완료.
=> 우선순위에 따라서 프라이머리가 정해진다.
3. 성능튜닝
1) 프로파일러 설정
2) Index와 find의 성능
- find 명령실행시 검색 우선순위는 제한된 검색조건 -> and -> or조건 순으로 우선순위를 결정한다.
- 컴파운드 인덱스의 경우 좌측부터 우측순으로 우선순위를 결정한다.
- 인덱스의 우선순위가 or조건절을 이용할 경우 인덱스를 사용하지 않는다. -> basicCursor. 이는 인덱스 사용이 더 많은 비용이 발생한다고 판단되기 때문이다.
- index가 없는 상태에서 hint를 이용할 경우 더 느려진 성능이 보여진다. index + find로 보인다.
- 인덱스가 여러개일 경우, 갯수가 적은 필드조건의 값으로 인덱스가 선정된다.
댓글 없음:
댓글 쓰기