'MongoDB'에 해당되는 글 4건

  1. 2013.01.11 MongoDB Java Tutorial..
  2. 2013.01.11 MongoDB Authentication 적용.
  3. 2013.01.11 MongoDB 막 설치해보기
  4. 2012.05.03 MongoDB - Strategies when hitting disk

MongoDB Java Tutorial..

ITWeb/개발일반 2013. 1. 11. 13:56


문서가 너무 잘되어 있어서 그냥 링크만 걸어 봅니다.

[MongoDB Original API]
http://www.mongodb.org/display/DOCS/Java+Tutorial

[Springframework API]
http://www.springsource.org/spring-data/mongodb
http://www.mkyong.com/mongodb/spring-data-mongodb-hello-world-example/


:

MongoDB Authentication 적용.

ITWeb/개발일반 2013. 1. 11. 13:33

몽고 문서에 잘 나와 있내요.
http://docs.mongodb.org/manual/tutorial/control-access-to-mongodb-with-authentication/

rs0:PRIMARY> use admin

switched to db admin

rs0:PRIMARY> db.addUser("henry", "1111")

{

        "user" : "henry",

        "readOnly" : false,

        "pwd" : "16c0f96a725f2b331d1a0359c7305d81",

        "_id" : ObjectId("50ef9510cfc8ac6e4cc62ae2")

}

rs0:PRIMARY> show dbs

admin   0.203125GB

demo    0.203125GB

local   6.0126953125GB

rs0:PRIMARY> use demo

switched to db demo

rs0:PRIMARY> db.addUser("henry", "1111")

{

        "user" : "henry",

        "readOnly" : false,

        "pwd" : "16c0f96a725f2b331d1a0359c7305d81",

        "_id" : ObjectId("50ef9542cfc8ac6e4cc62ae3")

}

rs0:PRIMARY> db.auth("henry", "1111")

1

rs0:PRIMARY>


:

MongoDB 막 설치해보기

ITWeb/개발일반 2013. 1. 11. 11:52

본 내용은 보안이 전혀 고려되지 않은 단순 설치 및 분산구성 테스트를 목적으로 작성되었습니다.
그러니 꼭 보안 관련 내용을 반영 하시기 바랍니다. ^^;
추후 보안 관련 내용도 올려 보도록 하겠습니다.

참고문서

MongoDB 설치하기
    [다운로드 및 설정]
        # 32bits
        curl http://downloads.mongodb.org/linux/mongodb-linux-i686-2.2.2.tgz > mongo.tgz
        # 64bits
        curl http://downloads.mongodb.org/linux/mongodb-linux-x86_64-2.2.2.tgz > mongo.tgz
        tar -xvzf mongo.tgz
        mv mongodb-linux-i686-2.2.2 ../apps/
        cd ../apps/
        ln -s mongodb-linux-i686-2.2.2 mongodb
        cd mongodb
        mkdir data
        mkdir conf
        mkdir logs
        cd conf
        vi mongodb.conf
            dbpath=/home/user/apps/mongodb/data
            logpath=/home/user/apps/mongodb/logs/mongodb.log
            logappend=true
            verbose=true
 
            #bind_ip=127.0.0.1
            port=27017
            fork=true
 
            rest=true
            #auth=true
            #noauth=true
    [실행]
        ./bin/mongod --config conf/mongodb.conf
 
    [접속]
        ./bin/mongo localhost:27017
 
    [중지]
        # mogod 로 중지
        mongod --config conf/mongodb.conf --shutdown
 
        # console 에서 아래 명령어 실행
        db.shutdownServer()
 
        # Ctrl+C, kill -2 PID, kill -15 PID 로 중지, kill -9 PID 사용 시 데이터 깨질 수 있음
        # kill 시그널 number
            1) SIGHUP 2) SIGNT 3) SIGQUIT 4) SIGILL
            5) SIGTRAP 6) SIGIOT 7) SIGBUS 8) SIGPPE
            9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
            13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
            18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
            22) SIGTTOL 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
            26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
            30) SIGPWR
MongoDB Replica 구성하기
    [Replica 설정]
        cd apps/mongodb
        mkdir -p srv/mongodb/rs0-0 srv/mongodb/rs0-1 srv/mongodb/rs0-2
        mkdir logs conf
        cd conf
        vi mongodb0.conf mongodb1.conf mongodb2.conf
            dbpath=/home/user/apps/mongodb/srv/mongodb/rs0-0
            logpath=/home/user/apps/mongodb/logs/mongodb0.log
            logappend=true
            verbose=true
            bind_ip=10.101.254.223
            port=27017
            fork=true
            rest=true
            replSet=rs0
 
            dbpath=/home/user/apps/mongodb/srv/mongodb/rs0-1
            logpath=/home/user/apps/mongodb/logs/mongodb1.log
            logappend=true
            verbose=true
            bind_ip=10.101.254.223
            port=27018
            fork=true
            rest=true
            replSet=rs0
 
            dbpath=/home/user/apps/mongodb/srv/mongodb/rs0-2
            logpath=/home/user/apps/mongodb/logs/mongodb2.log
            logappend=true
            verbose=true
            bind_ip=10.101.254.223
            port=27019
            fork=true
            rest=true
            replSet=rs0
 
    [실행]
        ./mongod --config ../conf/mongodb0.conf
        ./mongod --config ../conf/mongodb1.conf
        ./mongod --config ../conf/mongodb2.conf
 
    [접속]
        ./mongo 10.101.254.223:27017
 
    [RepliSet 구성]
        # mongodb.conf 로 구성하는 경우
            replSet=rs0/10.101.254.223:27017,10.101.254.223:27018,10.101.254.223:27019
        # command 로 구성 하는 경우
        ./mongo 10.101.254.223:27017
        MongoDB shell version: 2.2.2
        connecting to: 10.101.254.223:27017/test
        > rs.status();
        {
                "startupStatus" : 3,
                "info" : "run rs.initiate(...) if not yet done for the set",
                "errmsg" : "can't get local.system.replset config from self or any seed (EMPTYCONFIG)",
                "ok" : 0
        }
        > rs.initiate();
        {
                "info2" : "no configuration explicitly specified -- making one",
                "me" : "10.101.254.223:27017",
                "info" : "Config now saved locally.  Should come online in about a minute.",
                "ok" : 1
        }
        > rs.conf();
        {
                "_id" : "rs0",
                "version" : 1,
                "members" : [
                        {
                                "_id" : 0,
                                "host" : "10.101.254.223:27017"
                        }
                ]
        }
        rs0:PRIMARY> rs.add("10.101.254.223:27018");
        { "ok" : 1 }
        rs0:PRIMARY> rs.add("10.101.254.223:27019");
        { "ok" : 1 }
        rs0:PRIMARY> rs.status();
        {
                "set" : "rs0",
                "date" : ISODate("2013-01-10T08:35:22Z"),
                "myState" : 1,
                "members" : [
                        {
                                "_id" : 0,
                                "name" : "10.101.254.223:27017",
                                "health" : 1,
                                "state" : 1,
                                "stateStr" : "PRIMARY",
                                "uptime" : 295,
                                "optime" : Timestamp(1357806905000, 1),
                                "optimeDate" : ISODate("2013-01-10T08:35:05Z"),
                                "self" : true
                        },
                        {
                                "_id" : 1,
                                "name" : "10.101.254.223:27018",
                                "health" : 1,
                                "state" : 5,
                                "stateStr" : "STARTUP2",
                                "uptime" : 28,
                                "optime" : Timestamp(0, 0),
                                "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                                "lastHeartbeat" : ISODate("2013-01-10T08:35:20Z"),
                                "pingMs" : 0
                        },
                        {
                                "_id" : 2,
                                "name" : "10.101.254.223:27019",
                                "health" : 1,
                                "state" : 6,
                                "stateStr" : "UNKNOWN",
                                "uptime" : 17,
                                "optime" : Timestamp(0, 0),
                                "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                                "lastHeartbeat" : ISODate("2013-01-10T08:35:21Z"),
                                "pingMs" : 107,
                                "errmsg" : "still initializing"
                        }
                ],
                "ok" : 1
        }
        rs0:PRIMARY>
MongoDB Shard & Collection 구성하기
    [Shard & Collection]
         
        database : Database Name
        collection : Table Name (Object Name)
 
        [Config Server 구성]
            config server 폴더 생성
                [mongodb]$ mkdir -p configsvr0
                [mongodb]$ mkdir -p configsvr1
                [mongodb]$ mkdir -p configsvr2
                [mongodb]$ pwd
                /home/user/apps/mongodb/srv/mongodb
            [설정]
                - mongodb-configsvr0.conf
                dbpath=/home/user/apps/mongodb/srv/mongodb/configsvr0
                logpath=/home/user/apps/mongodb/logs/mongodb-configsvr0.log
                logappend=true
                verbose=true
                bind_ip=10.101.254.223
                port=37017
                fork=true
                rest=true
 
                - mongodb-configsvr1.conf
                dbpath=/home/user/apps/mongodb/srv/mongodb/configsvr1
                logpath=/home/user/apps/mongodb/logs/mongodb-configsvr1.log
                logappend=true
                verbose=true
                bind_ip=10.101.254.223
                port=37018
                fork=true
                rest=true
 
                - mongodb-configsvr2.conf
                dbpath=/home/user/apps/mongodb/srv/mongodb/configsvr2
                logpath=/home/user/apps/mongodb/logs/mongodb-configsvr2.log
                logappend=true
                verbose=true
                bind_ip=10.101.254.223
                port=37019
                fork=true
                rest=true
 
            [실행]
            ./mongod --config ../conf/mongodb-configsvr0.conf --configsvr
            ./mongod --config ../conf/mongodb-configsvr1.conf --configsvr
            ./mongod --config ../conf/mongodb-configsvr2.conf --configsvr
 
    [Mongos 구성]
        [폴더생성]
            cd apps/mongodb
            mkdir -p srv/mongodb/shard
 
        [설정]
            conf/mongodb-shard.conf
                dbpath=/home/user/apps/mongodb/srv/mongodb/shard
                logpath=/home/user/apps/mongodb/logs/mongodb-shard.log
                configdb=10.101.254.223:37017,10.101.254.223:37018,10.101.254.223:37019
                logappend=true
                verbose=true
                bind_ip=10.101.254.223
                port=47017
                fork=true
                rest=true
 
        [실행]
            ./mongo 10.101.254.223:47017
            MongoDB shell version: 2.2.2
            connecting to: 10.101.254.223:47017/test
            mongos> use admin
            switched to db admin
            mongos> db.runCommand({addShard:"rs0/10.101.254.223:27017,10.101.254.223:27018,10.101.254.223:27019"})
            { "shardAdded" : "rs0", "ok" : 1 }
            mongos> db.runCommand({listshards:1})
            {
                    "shards" : [
                            {
                                    "_id" : "rs0",
                                    "host" : "rs0/10.101.254.223:27017,10.101.254.223:27018,10.101.254.223:27019"
                            }
                    ],
                    "ok" : 1
            }
            mongos> show dbs
            admin   (empty)
            config  0.046875GB
            mongos> use demo
            switched to db demo
            mongos> db.createCollection("tbl_demo")
            { "ok" : 1 }
            mongos> db.tbl_demo.validate();
            {
                    "raw" : {
                            "rs0/10.101.254.223:27017,10.101.254.223:27018,10.101.254.223:27019" : {
                                    "ns" : "demo.tbl_demo",
                                    "firstExtent" : "0:2000 ns:demo.tbl_demo",
                                    "lastExtent" : "0:2000 ns:demo.tbl_demo",
                                    "extentCount" : 1,
                                    "datasize" : 0,
                                    "nrecords" : 0,
                                    "lastExtentSize" : 8192,
                                    "padding" : 1,
                                    "firstExtentDetails" : {
                                            "loc" : "0:2000",
                                            "xnext" : "null",
                                            "xprev" : "null",
                                            "nsdiag" : "demo.tbl_demo",
                                            "size" : 8192,
                                            "firstRecord" : "null",
                                            "lastRecord" : "null"
                                    },
                                    "deletedCount" : 1,
                                    "deletedSize" : 8016,
                                    "nIndexes" : 1,
                                    "keysPerIndex" : {
                                            "demo.tbl_demo.$_id_" : 0
                                    },
                                    "valid" : true,
                                    "errors" : [ ],
                                    "warning" : "Some checks omitted for speed. use {full:true} option to do more thorough scan.",
                                    "ok" : 1
                            }
                    },
                    "valid" : true,
                    "ok" : 1
            }
            mongos> db.tbl_demo.save({"username":"henry"})
            mongos> db.tbl_demo.find()
            { "_id" : ObjectId("50ef785abb4a5b4a3a99acac"), "username" : "henry" }
            mongos> use admin
            switched to db admin
            mongos> db.runCommand({enablesharding:"demo"})
            { "ok" : 1 }
            mongos> db.runCommand({shardcollection: "demo.tbl_demo", key:{_id:1}});
            { "collectionsharded" : "demo.tbl_demo", "ok" : 1 }
            mongos> db.printShardingStatus();
            --- Sharding Status ---
              sharding version: { "_id" : 1, "version" : 3 }
              shards:
                    "_id" : "rs0""host" : "rs0/10.101.254.223:27017,10.101.254.223:27018,10.101.254.223:27019" }
              databases:
                    "_id" : "admin""partitioned" : false"primary" : "config" }
                    "_id" : "demo""partitioned" : true"primary" : "rs0" }
                            demo.tbl_demo chunks:
                                            rs0     1
                                    { "_id" : { $minKey : 1 } } -->> { "_id" : { $maxKey : 1 } } on : rs0 Timestamp(1000, 0)
 
            mongos>

:

MongoDB - Strategies when hitting disk

ITWeb/개발일반 2012. 5. 3. 09:46

역시 퍼왔습니다.. ^^;

[원본]

[원본 글]

MongoDB - Strategies when hitting disk

I gave a lightning talk on this at the London MongoDB User Group and thought I'd write it up here

MongoDB sucks when it hits disk (ignoring SSDs). The general advice is to never hit disk. What if you have to hit disk? Conversocial's new metrics infrastructure will allow people to see statistics for their Facebook and Twitter channels going back indefinitely. In general, the data being queried and updated will be in the past month and we can keep this is memory. But, we want to let them query the data going back further than this - which means hitting disk.

We found three good strategies for making hitting the disk less painful:

1. Use Single Big Documents

The naive implementation of our metrics system stored documents like this:

{ metric: "content_count", client: 5, value: 51, date: ISODate("2012-04-01 13:00"} 
{ metric: "content_count", client: 5, value: 49, date: ISODate("2012-04-02 13:00"}

An alternative implementation is:

{ metric: "content_count", client: 5, month: "2012-04"151249, ... }

In this case we have a single document that spans an entire month with the value for each day being a field inside the document.

For a simple test we filled our database so that we had ~7gb of data on an Amazon c1.medium instance (1.7gb RAM) then tested how long it would take to read the data for an entire year and averaged this over multiple runs:

  • Naive implementation: 1.6s for a single year
  • Single document per month: 0.3s

That's a huge difference. The reasoning behind it is fairly simple:

  • The naive implementation has a worst case scenario where it has to read from the disk for all 365 documents and each of these results in a random seek
  • Having a single document per month has a worst case scenario where it has to read from the disk for 12 documents

An added benefit of this strategy is that there is less overhead per day which means the working set can contain much more data.

Foursquare do this.

2. Unusual Indices

Sometimes it pays to experiment with unusual index layouts. The naive index for our metrics system is on metric, client and then date:

db.metrics.ensureIndex({ metric: 1, client: 1, date: 1})

A common tip with indexing is to have all new values go to one side of the index. We reasoned that although the date was at the end of our index we would be writing to the right of lots of parts of the index so performance should be OK. We were wrong. We compared the performance of the above index with a new one:

db.metrics.ensureIndex({ date: 1, metric: 1, client: 1 })
  • The naive implementation performed 10k/sec inserts but after 20 million inserts the performance dropped down to 2.5k/sec inserts and occasionally stalled with lots of IO to disk. Ouch
  • By switching to date at the start of the index our performance was kept constant at 10k/sec inserts

What about queries? By putting the date at the front of the index we realised we'd now have to query an entire year of data using an in query:

db.metrics.find({ 
    metric: 'content_count', client: 1, date: { $in: [ "2012-01""2012-02", ... ] } 
})

A test of the read performance of this displayed no noticeable impact.

The reasoning for this is that the naive implementation will be causing a lot of rebalancing of the trees used for the index. By switching the index around we ensured that all inserts went to one side of the index and rebalancing became a trivial operation.

3. Pre-Allocate for Locality

For most disks (not SSDs) the sequential read performance is vastly better than the random read performance. This means that we can read our metrics really fast from disk if we read them all from the same part of the disk. With MongoDB documents will reside on disk in the order that you wrote them unless they are resized and need to be moved around.

If we pre-allocate zero filled documents then we can force values for nearby months for the same metric to be stored on disk in the same location and then exploit the speed of sequential reads:

db.metrics.insert([ 
    { metric: 'content_count', client: 3, date: '2012-01'001020, ... } 
    { .................................., date: '2012-02', ... }
    { .................................., date: '2012-03', ... }
    { .................................., date: '2012-04', ... }
    { .................................., date: '2012-05', ... }
    { .................................., date: '2012-06', ... }
    { .................................., date: '2012-07', ... }
    { .................................., date: '2012-08', ... }
    { .................................., date: '2012-09', ... }
    { .................................., date: '2012-10', ... }
    { .................................., date: '2012-11', ... }
    { .................................., date: '2012-12', ... }
]) 
 

Now, when client 3 wants their values for 'content_count' for the past year we can serve it using one big sequential read.

And the benchmarks?

  • Reading an entire year without pre-allocation: 62ms
  • Reading an entire year with pre-allocation: 6.6ms

Despite the performance gains from this we decided not to do this. Pre-allocation can get expensive for sparse data: you end up wasting a lot of space storing zeros that are never changed.

Conclusions

MongoDB can be made to have decent disk performance. You've just got to do some of the work yourself to ensure that reads aren't too expensive.


: