Post List

2015년 8월 14일 금요일

MongoDB Study #19 Sharding System 1/2 : 구성 및 Test

1.  Sharding System

Big Data 환경에서 초당 몇 만건 이상의 Data를 저장하는 것은 흔한 일입니다. 이렇게 저장된 Data를 이용해서 필요할땐 통계 정보로 가공 처리를 해야 하는데 처리 할때에도 계속해서 Data를 저장하는 일에 지장을 주어서는 안됩니다. 그렇게 하기 위해서는 분산 처리를 하면 훨씬 더 효과적으로 저장 및 처리가 가능합니다.  MongoDB에서 이런 분산 저장 및 처리 기술을 Sharding System이라 합니다.

Sharding System의 목적을 3가지로 요약 할 수 있습니다.
- Data 분산 저장과 관리
- 빠른 성능
- Data의 Backup과 Restore의 편리성 제공

2. Shard Server

- Sharding System은 3대 이상의 Shard Server로 구축하는게 좋습니다. (최소 2대 이상이지만 성능 보장이 안됩니다.)
- Single Node로 운영할 때보다 최소 20 ~ 30 % 이상의 추가 메모리가 요구됩니다. (MongoSOpLog, Balancer Process가 사용할 공간)
- Config Server는 최소 3대 이상 활성화 할 것을 권장합니다. Config Server는 Sharding System의 Meta Data를 저장하며, 빠른 검색을 위한 Index를 관리하기 때문에 Shard Server와는 다른 Server에 구축하는 것이 원칙입니다. (최소 1대의 Config Server가 요구되지만 장애 발생을 대비한다면 추가 Config Server가 필요합니다. Config Server는 Shard Server보다는 저 사양으로도 구축 가능합니다.)

* 실습

일단 1대의 PC에 3개에 Shard Server를 구축해보겠습니다.
- Node 1 : C:/MongoDB/Shard1
- Node 2 : C:/MongoDB/Shard2
- Node 3 : C:/MongoDB/Shard3

먼저 경로를 생성합니다.
C:\>CD C:/MongoDB
C:\MongoDB>MD Shard1
C:\MongoDB>MD Shard2
C:\MongoDB>MD Shard3

이제 Shard Node 3대를 각각의 Command 창에서 실행해 보겠습니다.

- Node 1 (Port : 40001)
mongod --shardsvr --dbpath C:/MongoDB/Shard1 --port 40001
...
2015-08-14T10:03:00.286+0900 I NETWORK  [initandlisten] waiting for connections on port 40001

- Node 2 (Port : 40002)
mongod --shardsvr --dbpath C:/MongoDB/Shard2 --port 40002
...
2015-08-14T10:03:00.286+0900 I NETWORK  [initandlisten] waiting for connections on port 40002

- Node 3 (Port : 40003)
mongod --shardsvr --dbpath C:/MongoDB/Shard3 --port 40003
...
2015-08-14T10:03:00.286+0900 I NETWORK  [initandlisten] waiting for connections on port 40003

3. Config Server

- Sharding System에서 최소 1대가 필수적으로 요구됩니다.
- 장애 발생을 대비하기 위해서는 Config Server를 추가로 설치해야 합니다. 물론 원래 Config Server와는 다른 Server에 설치해야 합니다. 별도 Server에 구축이 힘들면 Shard Server 중 한 곳에 설치하는 방법도 있습니다.
- 한대의 Config Server 가 다운되면 나머지 Config Server는 Read Only로 운영됩니다.
- Config Server에는 어떤 Data들이 어떻게 분산 저장되는지 Meta Data가 저장되며, MongoS가 Data Read/Write 작업을 할때 Config Server를 통해 수집합니다.

* 실습

- Config 1 : C:/MongoDB/Config1
- Config 2 : C:/MongoDB/Config2
- Config 3 : C:/MongoDB/Config3

먼저 경로를 생성합니다.
C:\>CD C:/MongoDB
C:\MongoDB>MD Config1
C:\MongoDB>MD Config2
C:\MongoDB>MD Config3

이제 Config Server 3대를 각각의 Command 창에서 실행해 보겠습니다.

- Config Server 1 (Port : 50001)
mongod --configsvr --dbpath c:/MongoDB/Config1 --port 50001
...
2015-08-14T10:11:37.628+0900 I NETWORK  [initandlisten] waiting for connections on port 50001

- Config Server 2 (Port : 50002)
mongod --configsvr --dbpath c:/MongoDB/Config2 --port 50002
...
2015-08-14T10:11:37.628+0900 I NETWORK  [initandlisten] waiting for connections on port 50002

- Config Server 3 (Port : 50003)
mongod --configsvr --dbpath c:/MongoDB/Config3 --port 50003
...
2015-08-14T10:11:37.628+0900 I NETWORK  [initandlisten] waiting for connections on port 50003

4. MongoS Process

- Big Data를 Shard Server로 분배해주는 Process 입니다.
- Application Server에서 실행이 가능합니다.
- Config Server로부터 Meta Data를 Cache 합니다.

MongoS Process를 활성화하여 Shard Server를 등록해야 합니다.
mongos --configdb localhost:50001,localhost:50002,localhost:50003 --port 50000 --chunkSize 1
...
2015-08-14T10:43:43.922+0900 I NETWORK  [mongosMain] SyncClusterConnection connecting to [localhost:50001]
2015-08-14T10:43:43.923+0900 I NETWORK  [mongosMain] SyncClusterConnection connecting to [localhost:50002]
2015-08-14T10:43:43.923+0900 I NETWORK  [mongosMain] SyncClusterConnection connecting to [localhost:50003]
...

Client Program으로 MongoS에 접속하여 각 Shard Server를 등록하고 관련 Collection의 Shard Key를 등록합니다. (MongoS의 기본 Port는 27017)
C:\>mongo localhost:50000/admin
MongoDB shell version: 3.0.5
connecting to: localhost:50000/admin
mongos> db.runCommand( { addshard : "localhost:40001" } )
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> db.runCommand( { addshard : "localhost:40002" } )
{ "shardAdded" : "shard0001", "ok" : 1 }
mongos> db.runCommand( { addshard : "localhost:40003" } )
{ "shardAdded" : "shard0002", "ok" : 1 }
mongos> db.runCommand( { enablesharding : "test" } )
{ "ok" : 1 }

Sharding은 Collection 단위로 수행되며 Shard-Key (특정 Field)를 기준으로 분산됩니다.
즉 Sharding을 위해서는 반드시 Index 생성이 요구됩니다.
mongos> use test
mongos> db.emp.createIndex( { empno : 1 } )
{
        "raw" : {
                "localhost:40001" : {
                        "createdCollectionAutomatically" : true,
                        "numIndexesBefore" : 1,
                        "numIndexesAfter" : 2,
                        "ok" : 1
                }
        },
        "ok" : 1
}
mongos> use admin
switched to db admin
mongos> db.runCommand( { shardcollection : "test.emp", key : { empno : 1 } } )
{ "collectionsharded" : "test.emp", "ok" : 1 }

5. Shard 환경설정 확인

mongos> db.runCommand( { listshards : 1 } ) // 설정된 Shard Server 확인
{
        "shards" : [
                {
                        "_id" : "shard0000",
                        "host" : "localhost:40001"
                },
                {
                        "_id" : "shard0001",
                        "host" : "localhost:40002"
                },
                {
                        "_id" : "shard0002",
                        "host" : "localhost:40003"
                }
        ],
        "ok" : 1
}
mongos> use config
switched to db config
mongos> db.locks.find( { _id : "balancer" } ).pretty() // Balancer 상태
{
        "_id" : "balancer",
        "state" : 0,
        "who" : "SJYUN-ATIV:50000:1439516624:41:Balancer:41",
        "ts" : ObjectId("55cd4d4fcf7a6c982f5a6f7e"),
        "process" : "SJYUN-ATIV:50000:1439516624:41",
        "when" : ISODate("2015-08-14T02:07:11.758Z"),
        "why" : "doing balance round"
}
mongos> db.getCollection("version").findOne()
{
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("55cd47d1cf7a6c982f5a6e6f")
}
mongos> db.settings.find()
{ "_id" : "chunksize", "value" : 1 }
mongos> db.shards.find()
{ "_id" : "shard0000", "host" : "localhost:40001" }
{ "_id" : "shard0001", "host" : "localhost:40002" }
{ "_id" : "shard0002", "host" : "localhost:40003" }
mongos> db.collections.find()
{ "_id" : "test.emp", "lastmod" : ISODate("2015-08-14T02:02:41.183Z"), "dropped" : false, "key" : { "empno" : 1 }, "unique" : false, "lastmodEpoch" : ObjectId("55cd4c41cf7a6c982f5a6f4a") }
mongos> db.mongos.find() // MongoS 상태 확인
{ "_id" : "SJYUN-ATIV:50000", "ping" : ISODate("2015-08-14T02:08:56.906Z"), "up" : 1511, "waiting" : true, "mongoVersion" : "3.0.5" } 

6. Test

현재 실행중인 Client에서 아래와 같이 입력합니다.
use test
for ( var i = 0; i <= 100000; i++) db.emp.save( { empno : i , ename : "test" } )

다른 Client를 하나 더 띄워서 아래와 같이 입력합니다.
C:\>mongo localhost:50000/test
MongoDB shell version: 3.0.5
connecting to: localhost:50000/test
mongos> for (var n = 100000; n < 200000; n++) db.emp.save( { empno : n , sal : 1000} )
WriteResult({ "nInserted" : 1 })

총 20만건의 Data를 2대의 Client에서 각각 10만건씩 입력하였습니다.
각 Shard 별로 어떻게 분산 입력되었는지 확인해 보겠습니다.

2개의 Client 중 하나에서 아래와 같이 실행해 보겠습니다.
mongos> exit
bye
C:\Users\icysw_000>mongo localhost:40001/test
MongoDB shell version: 3.0.5
connecting to: localhost:40001/test
> db.emp.count()
11783
> exit
bye
C:\Users\icysw_000>mongo localhost:40002/test
MongoDB shell version: 3.0.5
connecting to: localhost:40002/test
> db.emp.count()
11627
> exit
bye
C:\Users\icysw_000>mongo localhost:40003/test
MongoDB shell version: 3.0.5
connecting to: localhost:40003/test
> db.emp.count()
176601
> exit
bye
C:\Users\icysw_000>mongo localhost:50000/test
MongoDB shell version: 3.0.5
connecting to: localhost:50000/test
mongos> sh.status()  // Shard 상태 확인
--- Sharding Status ---
  sharding version: {
        "_id" : 1,
        "minCompatibleVersion" : 5,
        "currentVersion" : 6,
        "clusterId" : ObjectId("55cd47d1cf7a6c982f5a6e6f")
}
  shards:
        {  "_id" : "shard0000",  "host" : "localhost:40001" }
        {  "_id" : "shard0001",  "host" : "localhost:40002" }
        {  "_id" : "shard0002",  "host" : "localhost:40003" }
  balancer:
        Currently enabled:  yes
        Currently running:  yes
                Balancer lock taken at Fri Aug 14 2015 12:18:58 GMT+0900 (대한민국 표준시) by SJYUN-ATIV:50000:1439516624:41:Balancer:41
        Failed balancer rounds in last 5 attempts:  0
        Migration Results for the last 24 hours:
                4 : Success
                3 : Failed with error 'could not acquire collection lock for test.emp to migrate chunk [{ : MinKey },{ : MaxKey }) :: caused by :: Lock for migrating chunk [{ : MinKey }, { : MaxKey }) in test.emp is taken.', from shard0002 to shard0000
                49 : Failed with error 'moveChunk failed to engage TO-shard in the data transfer: can't accept new chunks because  there are still 3 deletes from previous migration', from shard0002 to shard0000
  databases:
        {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
        {  "_id" : "test",  "partitioned" : true,  "primary" : "shard0000" }
                test.emp
                        shard key: { "empno" : 1 }
                        chunks:
                                shard0000       2
                                shard0001       3
                                shard0002       34
                        too many chunks to print, use verbose if you want to force print 

댓글 없음:

댓글 쓰기