你的位置:首页 > 数据库类

MongoDB入门学习(四)

2014-05-29 浏览:(6259) 数据库类 评论(0)

九、MapReduce

能完成count、distinct、group的所有功能

db.runCommand(
{
    mapreduce:'zxq',
    map:function(){emit(this.name.substr(0,3),this);},
    reduce:function(key,vals){return vals[0];},  //注意:vals是一个Object对象而不是数组
    out:'wq'
});


{
    "result" : "wq",
    "timeMillis" : 124,
    "counts" : {
        "input" : 4000,
        "emit" : 4000,
        "reduce" : 387,
        "output" : 99
    },
    "ok" : 1
}


注意:
1.mapreduce是根据map函数里调用的emit函数的第一个参数来进行分组的
2.仅当根据分组键分组后一个键匹配多个文档,才会将key和文档集合交由reduce函数处理。

db.runCommand(
{
    mapreduce:'zxq',
    map:function(){emit(this.name.substr(0,3),this);},
    reduce:function(key,vals){return 'wq';}, 
    out:'wq'
}); 
//查看wq表数据

> show collections
a
ccc
system.indexes
users
wq
zxq

> db.wq.find()
{ "_id" : "a1", "value" : "wq" }
{ "_id" : "a10", "value" : "wq" }
{ "_id" : "a11", "value" : "wq" }
{ "_id" : "a12", "value" : "wq" }
{ "_id" : "a13", "value" : "wq" }
{ "_id" : "a14", "value" : "wq" }
{ "_id" : "a15", "value" : "wq" }
{ "_id" : "a16", "value" : "wq" }
{ "_id" : "a17", "value" : "wq" }
{ "_id" : "a18", "value" : "wq" }
{ "_id" : "a19", "value" : "wq" }
{ "_id" : "a2", "value" : "wq" }
{ "_id" : "a20", "value" : "wq" }
{ "_id" : "a21", "value" : "wq" }
{ "_id" : "a22", "value" : "wq" }
{ "_id" : "a23", "value" : "wq" }
{ "_id" : "a24", "value" : "wq" }
{ "_id" : "a25", "value" : "wq" }
{ "_id" : "a26", "value" : "wq" }
{ "_id" : "a27", "value" : "wq" }
Type "it" for more

//案例二:group的功能
> map = function() { for (var key in this) { emit(key, {count : 1}); }};
> reduce = function(key, emits) { total = 0; for (var i in emits) { total += emits[i].count; } return {"count" : total}; }

> db.runCommand({"mapreduce" : "zxq", "map" : map, "reduce" : reduce,"out":"result"})
{
    "result" : "result",
    "timeMillis" : 307,
    "counts" : {
        "input" : 4000,
        "emit" : 12000,
        "reduce" : 120,
        "output" : 3
    },
    "ok" : 1
}

//结果集
> db.result.find()
{ "_id" : "_id", "value" : { "count" : 4000 } }
{ "_id" : "id", "value" : { "count" : 4000 } }
{ "_id" : "name", "value" : { "count" : 4000 } }

删除记录

> db.zxq.remove({id:1})
> db.zxq.find()
> db.zxq.deleteOne({id:2})
{ "acknowledged" : true, "deletedCount" : 1 }
> db.zxq.find({})
{ "_id" : ObjectId("57c2ce75b854b5b8198eebdb"), "id" : 3, "name" : "c" }
> 
> db.zxq.deleteMany({"name" : "a"})
{ "acknowledged" : true, "deletedCount" : 1 }
> db.zxq.find({})
{ "_id" : ObjectId("57c2ce75b854b5b8198eebdb"), "id" : 3, "name" : "c" }
{ "_id" : ObjectId("57c2d006b854b5b8198eebdd"), "id" : 2, "name" : "b" }
{ "_id" : ObjectId("57c2d006b854b5b8198eebde"), "id" : 3, "name" : "c" }
>

十、游标

创建测试表

> for (i=1;i<=1000;i++){db.zxq.insert({id:i,name:"a"+i})}

定义游标

var cursor = db.zxq.find();
while (cursor.hasNext()){obj=cursor.next();print(obj.id);}
//增加函数
> db.zxq.find().limit(3)   //显示前面3行
{ "_id" : ObjectId("57cbbbe7c2993ede6eb626f6"), "id" : 1, "name" : "a1" }
{ "_id" : ObjectId("57cbbbe7c2993ede6eb626f7"), "id" : 2, "name" : "a2" }
{ "_id" : ObjectId("57cbbbe7c2993ede6eb626f8"), "id" : 3, "name" : "a3" }
> db.zxq.find().skip(3).limit(3)  //跳过前面3行,显示3行
{ "_id" : ObjectId("57cbbbe7c2993ede6eb626f9"), "id" : 4, "name" : "a4" }
{ "_id" : ObjectId("57cbbbe7c2993ede6eb626fa"), "id" : 5, "name" : "a5" }
{ "_id" : ObjectId("57cbbbe7c2993ede6eb626fb"), "id" : 6, "name" : "a6" }
  > db.zxq.find().limit(3).sort({id:-1}) //降序排序
{ "_id" : ObjectId("57cbbbe7c2993ede6eb62add"), "id" : 1000, "name" : "a1000" }
{ "_id" : ObjectId("57cbbbe7c2993ede6eb62adc"), "id" : 999, "name" : "a999" }
{ "_id" : ObjectId("57cbbbe7c2993ede6eb62adb"), "id" : 998, "name" : "a998" }
> db.zxq.find().limit(3).sort({id:1}) //升序排序
{ "_id" : ObjectId("57cbbbe7c2993ede6eb626f6"), "id" : 1, "name" : "a1" }
{ "_id" : ObjectId("57cbbbe7c2993ede6eb626f7"), "id" : 2, "name" : "a2" }
{ "_id" : ObjectId("57cbbbe7c2993ede6eb626f8"), "id" : 3, "name" : "a3" }
//分页处理
var cursor1 = db.zxq.find().limit(100);
var cursor2 = db.zxq.find().skip(100).limit(100);
var cursor3 = db.zxq.find().skip(200).limit(100);
while (cursor1.hasNext()){obj=cursor1.next();print(obj.id);}
while (cursor2.hasNext()){obj=cursor2.next();print(obj.id);}
while (cursor3.hasNext()){obj=cursor3.next();print(obj.id);}

手动迭代游标

> var myCursor = db.users.find({status:"A"});
> myCursor
{ "_id" : ObjectId("57c2ba213b5e3ba4c68d0d7b"), "name" : "bob", "age" : 42, "status" : "A" }
{ "_id" : ObjectId("57c2ba213b5e3ba4c68d0d7c"), "name" : "ahn", "age" : 22, "status" : "A" }
> 

> var myCursor = db.users.find({status:"A"});
> myCursor.hasNext()
true

> print(tojson(myCursor.next()))
{
    "_id" : ObjectId("57c2ba213b5e3ba4c68d0d7b"),
    "name" : "bob",
    "age" : 42,
    "status" : "A"
}
> print(tojson(myCursor.next()))
{
    "_id" : ObjectId("57c2ba213b5e3ba4c68d0d7c"),
    "name" : "ahn",
    "age" : 22,
    "status" : "A"
}
> print(tojson(myCursor.next()))
Sun Aug 28 04:28:24.382 error hasNext: false at src/mongo/shell/query.js:124
> 

//游标2
> var myCursor = db.users.find({status:"A"});
> printjson(myCursor.next())
{
    "_id" : ObjectId("57c2ba213b5e3ba4c68d0d7b"),
    "name" : "bob",
    "age" : 42,
    "status" : "A"
}
> printjson(myCursor.next())
{
    "_id" : ObjectId("57c2ba213b5e3ba4c68d0d7c"),
    "name" : "ahn",
    "age" : 22,
    "status" : "A"
}

十一、GridFs

数据库中存放二进制文件超过16M时,使用GridFs,GridFS在数据库中,默认使用fs.chunks和fs.files来存储文件。其中fs.files集合存放文件的信息,fs.chunks存放文件数据。

[root@linux bin]# echo "zxq is good" >zxq.txt  //创建文件
[root@linux bin]# cat zxq.txt 
zxq is good
[root@linux bin]# ./mongofiles put zxq.txt    //文件传输到数据库中
connected to: 127.0.0.1
added file: { _id: ObjectId('57cc32ac747f6865ca501e58'), filename: "zxq.txt", chunkSize: 262144, uploadDate: new Date(1473000108668), md5: "39c87dd1241d8ab74494d88439b7ad9a", length: 12 }
done!
[root@linux bin]# 
> show collections      //查看数据库中文档
a
ccc
fs.chunks
fs.files
result
system.indexes
users
wq
zxq
> db.fs.files.find()   //查看表中的文件信息
{ "_id" : ObjectId("57cc32ac747f6865ca501e58"), "filename" : "zxq.txt", "chunkSize" : 262144, "uploadDate" : ISODate("2016-09-04T14:41:48.668Z"), "md5" : "39c87dd1241d8ab74494d88439b7ad9a", "length" : 12 }
[root@linux bin]# rm zxq.txt    //删除原始文件
rm: remove regular file `zxq.txt'? yes
[root@linux bin]# cat zxq.txt
cat: zxq.txt: No such file or directory
[root@linux bin]# 
[root@linux bin]# ./mongofiles list  //查看数据库中文件
connected to: 127.0.0.1
zxq.txt 12
[root@linux bin]# 
[root@linux bin]# ./mongofiles get zxq.txt  //从数据库中取出文件
connected to: 127.0.0.1
done write to: zxq.txt
[root@linux bin]# ls
bsondump  mongod       mongofiles   mongoperf     mongosniff  zxq.txt
db        mongodump    mongoimport  mongorestore  mongostat
mongo     mongoexport  mongooplog   mongos        mongotop
[root@linux bin]# cat zxq.txt 
zxq is good
[root@linux bin]# 
//传入第二个文件
[root@linux bin]# ./mongofiles put zxq1.txt 
connected to: 127.0.0.1
added file: { _id: ObjectId('57cc33e4d3e1c4b92d0e0374'), filename: "zxq1.txt", chunkSize: 262144, uploadDate: new Date(1473000420571), md5: "39c87dd1241d8ab74494d88439b7ad9a", length: 12 }
done!
[root@linux bin]# ./mongofiles list
connected to: 127.0.0.1
zxq.txt 12
zxq1.txt    12
> db.fs.files.find()  //查看数据库中文件信息
{ "_id" : ObjectId("57cc32ac747f6865ca501e58"), "filename" : "zxq.txt", "chunkSize" : 262144, "uploadDate" : ISODate("2016-09-04T14:41:48.668Z"), "md5" : "39c87dd1241d8ab74494d88439b7ad9a", "length" : 12 }
{ "_id" : ObjectId("57cc33e4d3e1c4b92d0e0374"), "filename" : "zxq1.txt", "chunkSize" : 262144, "uploadDate" : ISODate("2016-09-04T14:47:00.571Z"), "md5" : "39c87dd1241d8ab74494d88439b7ad9a", "length" : 12 }
//查找带有zxq的文件
[root@linux bin]# ./mongofiles search zxq
connected to: 127.0.0.1
zxq.txt 12
zxq1.txt    12
[root@linux bin]# ./mongofiles search zxq.txt
connected to: 127.0.0.1
zxq.txt 12
[root@linux bin]# 
Mongofiles参数说明:
–d 指定数据库 ,默认是fs,Mongofiles list –d testGridfs
-u –p 指定用户名,密码
-h  指定主机
-port 指定主机端口
-c 指定集合名,默认是fs
-t 指定文件的MIME类型,默认会忽略

十二、journal工作原理

journal文件在MongoDB中的作用相当于redo日志文件在oracle中的作用,它可以在即使服务器意外宕机的情况下,将数据库操作进行重演在64位的机器上,2.0以上版本默认是开启了journal的,但是在32位机器上,或者2.0以下的版本中,默认是不开启journal

默认情况下mongodb每100毫秒往journal文件中flush一次数据,不过这是在数据文件和journal文件处于同一磁盘卷上的情况,而如果数据文件和journal文件不在同一磁盘卷上时,默认刷新输出时间是30毫秒。不过这个毫秒值是可以修改的,可修改范围是2~300,值越低,刷新输出频率越高,数据安全度也就越高,但磁盘性能上的开销也更高。

journal文件是以“j._”开头命名的,且是append only的,如果1个journal文件满了1G大小,mongodb就会新创建一个journal文件来使用,一旦某个journal文件所记载的写操作都被使用过了,mongodb就会把这个journal文件删除。通常在journal文件所在的文件夹下,只会存在2~3个journal文件,除非你使用mongodb每秒都写入大量的数据。而使用 smallfiles 这个运行时选项可以将journal文件大小减至128M大小。

[root@primary journal]# pwd
/mongodb/bin/db/journal
[root@primary journal]# ls -l
total 3145740
-rw------- 1 root root 1073741824 Aug  6 19:03 j._0
-rw------- 1 root root 1073741824 Aug  4 08:01 prealloc.1
-rw------- 1 root root 1073741824 Aug  4 08:01 prealloc.2

首先要知道在这个原理中,存在着两个file,两个view。两个file是 data file 和 journal file,两个view是 shared view 和 private view。两个file是对磁盘而言的,而两个view是对内存而言的,下面以图解的方式解释:

启动服务前

启动服务后,MongoDB请求操作系统将Data file映射到Shared view,此时操作系统只管
映射这个动作,并不将数据加载到Shared view中,而是由MongoDB在需要时再将数据进行加载到Shared view。

然后,MongoDB再请求操作系统将Shared view映射到Private view,
之后MongDB对数据的读写操作都是直接操作的Private view

如果发生了写操作

Private view变脏以后,根据journalCommitInterval的设置,
将在一定时间后将写操作往Journal file中复制,这个过程称为“group commit”:

Journal file中记录的是原生的操作(raw operation),这些原生的操作可以
使MongoDB完成以下操作:
    对文档的插入/更新(document insertion/updates)
    对索引的修改(index modifications)
    对命名空间文件的修改(changes to the namespace files)
这些原生操作告诉了Journal file数据变化发生在Data file的什么位置。
至此,MongoDB上发生的写事件可以被认为是安全的了,因为这些写操作已
经被记录在了Journal file上,即使服务器掉电了,在下次启动MongoDB时,
Journal file上的写操作将会被重演。

接下来,Journal file中记录的写操作会应用在Shared view上:

默认每隔60秒,MongoDB请求操作系统将Shared view刷新输出到Data file:

数据就被写入到数据文件了。这时MongoDB还会将Journal file
中已输出到Data file的写操作删除掉(由于MongoDB在将Journal 
file中写操作放到Shared view时,是通过了一个前指针和一个后
指针来操作的,所以MongoDB知道哪些写操作是被放到Shared view了的,哪些没有)。
最后,MongoDB还会例行地如一开始一样,将Shared view映射
到Private view,以保持一致性(也是防止Private view变得太过于脏了)。

十三、MongoDB 做内存数据库使用

[root@primary bin]# mkdir /mongodata
[root@primary bin]# mount -t tmpfs -o size=2048M tmpfs /mongodata
[root@primary bin]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/rootvg-rootlv 93G   53G   36G  60% /
tmpfs                 1.5G   72K  1.5G   1% /dev/shm
/dev/sda1             194M   34M  151M  18% /boot
tmpfs                 2.0G     0  2.0G   0% /mongodata
mongodb参数文件
dbpath=/mongodata
//可以减少开销
nojournal = true
smallFiles = true
noprealloc = true
使用
> show dbs
local   0.078125GB
test    (empty)
> use zxquse zxq
switched to db zxq
> db.zxq.insert({name:"a"})> 
> 
> db.zxq.find()db.zxq.find()
{ "_id" : ObjectId("57a5c68ea9475fc6e6d4cb77"), "name" : "a" }
>

十四、数据导出方式备份

1、创建测试表

for(var i=1;i<1000;i++){db.t1.insert({name:"a"+i,age:i+1})}

2、导出表数据

mongoexport -h 192.168.111.111:27017 -d zxq -c t1 -o /mongodb/backup/t1.txt
connected to: 192.168.111.111:27017
exported 999 records

3、删除测试数据文档

[root@primary bin]# > use zxq
[root@primary bin]# > db.t1.drop()
[root@primary bin]# ./mongoimport -h 192.168.111.111:27017 -d zxq -c t1 /mongodb/backup/t1.txt
connected to: 192.168.111.111:27017
Thu Aug  4 19:51:02.880 check 9 999
Thu Aug  4 19:51:02.943 imported 999 objects

4、验证数据是否恢复

[root@primary bin]#> db.t1.count()
[root@primary bin]#> 999

十五、搭建主从备份

1、开启master服务器

[administrator@localhost ~]$ ./mongod --dbpath=/mongodb/master/db 
--master -port 27017 --logpath=/mongodb/master/logs/mongodb.log --fork
--master  标记自己是master服务器。
--port    指定自己的端口,默认是27017
--fork    后台运行启动进程

2、开启slave服务器

[administrator@localhost ~]$ 
./mongod --dbpath=/mongodb/slave/db --slave --source=127.0.0.1:27017 
--port 27018 --logpath=/mongodb/slave/logs/mongodb.log --fork
--slave:   标记自己是slave服务器
--source:  标记我需要同步的服务器是谁? 指定的ip。
--port:     开启自己的端口,千万不能和master重复。
--fork      后台运行启动进程

十六、副本集=>双机热备

配置参数及启动主从库

1、master上

配置文件master.conf
port=27017
dbpath=/mongodb/master/db
replSet=zxq/127.0.0.1:27018 (zxq为副本名称)
启动:
[root@primary master]# ./mongod --config=/mongodb/master/master.conf --fork

2、standby上

配置文件standby.conf
port=27018
dbpath=/mongodb/standby/db
replSet=zxq/127.0.0.1:27017 (zxq为副本名称)
启动:
[root@primary standby]# ./mongod --config=/mongodb/standby/standby.conf 

注:
//如果有第三台
port=27019
dbpath=/mongodb/standby/db
replSet=zxq/127.0.0.1:27017,127.0.0.1:27018 (zxq为副本名称)

十七、配置主从同步

1、创建过程

//连接到主admin库
[root@primary master]# ./mongo 127.0.0.1:27017/admin
MongoDB shell version: 2.4.9
connecting to: 127.0.0.1:27017/admin
> 
//运行主从同步配置命令
db.runCommand({"replSetInitiate":{ "_id":"zxq", "members":
[ {"_id":1,"host":"127.0.0.1:27017"}, {"_id":2,"host":"127.0.0.1:27018"} ]}})

注:
                 zxq  //副本名称
    "_id":1和"_id":2  //两个节点的节点ID,不能冲突

2、启动过程日志信息

主节点日志
Thu Aug  4 11:29:11.348 [rsStart] trying to contact 127.0.0.1:27018
Thu Aug  4 11:29:11.385 [rsStart] replSet I am 127.0.0.1:27017     //提示本节点信息
Thu Aug  4 11:29:11.385 [rsStart] replSet STARTUP2
Thu Aug  4 11:29:11.388 [rsMgr] replSet total number of votes is even - add arbiter or give one member an extra vote
Thu Aug  4 11:29:11.390 [rsHealthPoll] replSet member 127.0.0.1:27018 is up  //提示从节点启动 
Thu Aug  4 11:29:12.387 [rsSync] replSet SECONDARY
//从节点日志
Thu Aug  4 11:29:11.408 [rsStart] replSet I am 127.0.0.1:27018
Thu Aug  4 11:29:11.408 [rsStart] replSet got config version 1 from a remote, saving locally
Thu Aug  4 11:29:11.408 [rsStart] replSet info saving a newer config version to local.system.replset
Thu Aug  4 11:29:11.412 [rsStart] replSet saveConfigLocally done
Thu Aug  4 11:29:11.412 [rsStart] replSet STARTUP2
Thu Aug  4 11:29:11.413 [rsMgr] replSet total number of votes is even - add arbiter or give one member an extra vote
Thu Aug  4 11:29:11.467 [rsSync] ******
Thu Aug  4 11:29:11.467 [rsSync] creating replication oplog of size: 2289MB...
Thu Aug  4 11:29:11.467 [FileAllocator] allocating new datafile /mongodb/standby/db/local.1, filling with zeroes...
Thu Aug  4 11:29:11.500 [FileAllocator] done allocating datafile /mongodb/standby/db/local.1, size: 2047MB,  took 0.033 secs 
//从节点接收到主节点的数据
Thu Aug  4 11:29:11.501 [FileAllocator] allocating new datafile /mongodb/standby/db/local.2, filling with zeroes...
Thu Aug  4 11:29:11.531 [FileAllocator] done allocating datafile /mongodb/standby/db/local.2, size: 2047MB,  took

3、检查主备节点是否生效

> rs.status()
{
"set" : "zxq",
"date" : ISODate("2016-08-04T03:31:25Z"),
"myState" : 1, 
"members" : [
{
"_id" : 1,  //站点ID
"name" : "127.0.0.1:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",  //主节点
"uptime" : 415,
"optime" : Timestamp(1470281344, 1),
"optimeDate" : ISODate("2016-08-04T03:29:04Z"),
"self" : true
},
{
"_id" : 2, //站点ID
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY", //从节点
"uptime" : 134,
"optime" : Timestamp(1470281344, 1),
"optimeDate" : ISODate("2016-08-04T03:29:04Z"),
"lastHeartbeat" : ISODate("2016-08-04T03:31:25Z"),
"lastHeartbeatRecv" : ISODate("2016-08-04T03:31:25Z"),
"pingMs" : 0,
"syncingTo" : "127.0.0.1:27017"
}
],
"ok" : 1
}

//备用节点
[root@primary standby]# ./mongo 127.0.0.1:27018
MongoDB shell version: 2.4.9
connecting to: 127.0.0.1:27018/test
zxq:SECONDARY> 
zxq:SECONDARY>  //已经是备用节点信息

4、添加仲裁节点

创建vote目录,复制mongod、mongo到目录,并创建db目录

//创建仲裁节点的配置问题
[root@primary vote]# vi vote.conf 
port=27019
dbpath=/mongodb/vote/db

//启动仲裁节点
[root@primary vote]# ./mongod --config=./vote.conf --fork

//在主节点上执行添加仲裁节点的命令
rs.addArb("127.0.0.1:27019")  //告诉主从27019是仲裁节点

5、仲裁添加完成后日志信息

27019上日志(仲裁节点)
Thu Aug  4 11:41:28.291 [conn3] end connection 127.0.0.1:27460 (2 connections now open)
Thu Aug  4 11:41:28.418 [rsHealthPoll] replSet member 127.0.0.1:27017 is up
Thu Aug  4 11:41:28.418 [rsHealthPoll] replSet member 127.0.0.1:27017 is now in state PRIMARY
//27017为PRIMARY
Thu Aug  4 11:41:28.422 [rsHealthPoll] replSet member 127.0.0.1:27018 is up
Thu Aug  4 11:41:28.422 [rsHealthPoll] replSet member 127.0.0.1:27018 is now in state SECONDARY
//27018为SECONDARY

主库上日志
Thu Aug  4 11:41:28.270 [rsHealthPoll] replset info 127.0.0.1:27019 thinks that we are down
Thu Aug  4 11:41:28.270 [rsHealthPoll] replSet member 127.0.0.1:27019 is up
Thu Aug  4 11:41:28.272 [rsHealthPoll] replSet member 127.0.0.1:27019 is now in state STARTUP2
Thu Aug  4 11:41:30.273 [rsHealthPoll] replSet member 127.0.0.1:27019 is now in state ARBITER
//27019已经正常

6、切换测试(停止主库)

//关闭主节点服务器进程
Thu Aug  4 11:49:05.375 [rsMgr] replSet info electSelf 2
Thu Aug  4 11:49:05.564 [rsMgr] replSet PRIMARY
Thu Aug  4 11:49:07.287 [rsHealthPoll] replset info 127.0.0.1:27017 heartbeat failed, retrying
Thu Aug  4 11:49:09.291 [rsHealthPoll] replset info 127.0.0.1:27017 heartbeat failed, retrying

//从库变主库
zxq:SECONDARY> 
zxq:PRIMARY> 
zxq:PRIMARY> 

//从库变主库,可以接管业务
zxq:SECONDARY> db.zxq.find()
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
zxq:PRIMARY> db.zxq.find()
db.zxq.find()
{ "_id" : ObjectId("57a2931b90d8e955cf551d2c"), "name" : "a", "age" : "10" }
{ "_id" : ObjectId("57a293fe90d8e955cf551d2d"), "name" : "b", "age" : "11" }
{ "_id" : ObjectId("57a2bd7106e8981bb7d168ea"), "name" : "c", "age" : "12" }

十八、分片

mongodb采用将集合进行拆分,然后将拆分的数据均摊到几个片上的一种解决方案

mongos就是一个路由服务器,它会根据管理员设置的“片键”将数据分摊到自己管理的mongod集群

数据和片的对应关系以及相应的配置信息保存在”config服务器”上

所有的client请求我们都是由 mongos去转向的,本身不存留数据

mongod: 一个普通的数据库实例,如果不分片的话,我们会直接连上mongod。

127.0.0.1:27017  作为 mongos服务器
127.0.0.1:27018  作为 config 服务器
127.0.0.1:28000  作为一个sharing1服务器
127.0.0.1:28001  作为一个sharing2服务器

配置基本服务

开启config服务器

其实就是一个普通的mongod服务。
/mongodb/config/mongod --port=27018 --dbpath=/mongodb/config/db

开启mongos服务

/mongodb/master/mongos --port=27017 configdb=127.0.0.1:27018

开启两个片键

/mongodb/s1/mongod --port=28000 --dbpath=/mongodb/s1/db
/mongodb/s2/mongod --port=28001 --dbpath=/mongodb/s2/db

初始化配置

将要作为“片”的机器放到mongos的config配置中

登录到mongos
/mongodb/bin/mongo 127.0.0.1:27017
connecting to: 127.0.0.1:27017/test

mongos> use admin
switched to db admin

mongos> db.runCommand({"addshard":"127.0.0.1:28000","allowLocal":true})
    { "shardAdded" : "shard0000", "ok" : 1 }
mongos> db.runCommand({"addshard":"127.0.0.1:28001","allowLocal":true})
    { "shardAdded" : "shard0001", "ok" : 1 }

准备分片文档

一定要在分片之前创建 “片键” 的索引

mongos> use test
switched to db test
mongos>db.zxq.insert({"name":"jack","age":1})
mongos> db.zxq.createIndex({"age":1})
循环插入数据:
for(var i=1;i<10000;i++){db.zxq.insert({"name":"jack"+i,"age":i})}

激活并创建分片

mongos> use admin
switched to db admin
mongos> db.runCommand({"enablesharding":"test"})
mongos> db.runCommand({"shardcollection":"test.zxq","key":{"age":1}})
{ "collectionsharded" : "test.zxq", "ok" : 1 }

查看分片

db.shards.find()


  • 发表评论
  • 查看评论
【暂无评论!】

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。