您的位置:首页 > 数据库 > Mongodb

MongoDB实战_PS : 操作性很强的入门手记

2014-04-23 10:10 148 查看
./mongo --port 27017

show dbs ----已有数据库列表

show collections ---- 已有集合列表

show users ----已有用户列表

use dbname ---- 切换数据库,系统会自动延迟创建该数据库

db.account.save({'name':'test','addr':'china'}) -- 创建集合

db.account.find() -- 查看集合数据

db.dropDatabase() -- 删除数据库

数据库组件:mongod、mongos、mongo

数据库工具:

mongodump -h dbhost -d dbname -o dbdirectory -- 数据库备份

mongorestore -h dbhost -d dbname --directoryperdb dbdirectory -- 数据库恢复

./bsondump dump/bbs/account.bson -- 查看bson对象

./mongoexport -d bbs -c account -q {} -f name,addr --csv > account.csv -- 数据导出工具,导出为csv格式

./mongoexport -d bbs -c account -q {} -f name,addr > account.json 导出为json格式

./mongoexport -d bbs -c account -q '{"name":"test2"}' -f name,addr --csv > account.csv 带查询条件导出

./mongoimport -d bbs -c account --type csv --headerline --drop < account.csv -- 数据导入工具,导入csv文件

./mongoimport -d bbs -c account --type json --drop < account.json--导入json文件

===================文档插入=======================

单个文档插入:db.account.insert({"userName" : "bbs10000001", "passwd" : "ddddddd", "acctAttr" : null })

===============文档删除=============

删除文档中所有数据:db.account.remove(),不删除索引

条件删除:db.account.remove({"userName":"bbs1100"})

删除整个集合:db.account.drop()。数据、索引一起删除,性能好

=============文档更新=====================

更新命令:db.account.update({"userName":"bbs10"},{ "_id" : "3e1fd26f4b0f8351760fcc54", "userName" : "bbs10", "passwd" : "fff", "acctAttr" : null })

$set用法,使用修改器进行局部更改:db.account.update({"_id" : "3e1fd26f4b0f8351760fcc54"},{ "$set":{"passwd":"d"}})

去掉一个键:db.account.update({"userName":"bbs10"},{ "$unset":{"passwd":1}})

$inc用法,db.account.update({"userName":"bbs10"},{ "$inc":{"age":30}})

加1:db.account.update({"userName":"bbs10"},{ "$inc":{"age":1}})

减1:db.account.update({"userName":"bbs10"},{ "$inc":{"age":-1}})

$inc的键值必须为数值。

数组修改器$push。db.account.update({"userName":"bbs10"},{$push:{"email":"1@163.com"}})

$addToSet避免重复加入:db.account.update({"userName":"bbs10"}},{$addToSet:{"email":"4@163.com"}})

pop修改器:db.account.update({"userName":"bbs10"},{$pop:{"email":1}}) 从数组尾删除一个元素

从数组头删除一个元素:db.account.update({"userName":"bbs10"},{$pop:{"email":-1}})

指定位置删除删除元素:db.account.update({"userName":"bbs10"},{$pull:{"email":"2@163.com"}})

多文档更新:db.account.update({"userName":"bbs10"},{$set:{"passwd":"a"}},false,true)

看执行结果,有多少文档被更新:db.runCommand({getLastError:1})

执行getLastError时,驱动程序会等待数据库返回结果

=====================查询========基础查询find命令==================

查询集合所有文档:db.account.find()

简单条件查询:db.account.find({"userName":"bbs10"})

多值匹配条件查询,类似"条件1 and 条件2":

db.account.find({"userName":"bbs10","passwd":"ddd"})

指定返回某些键:db.account.find({},{"userName":1,"passwd":1})

db.account.find({},{"passwd":0})

db.account.find({},{"userName":1,"_id":0})

=====================查询========复合条件查询==================

比较操作符lt、lte、gt、gte、ne分别对应<、<=、>、>=、!=

db.account.insert({"userName":"bbs2000000","age":30,"createTime":new Date()})

db.account.find({"createTime":{"$gt":start}})

db.account.find({"age":{"$gt":30,"$lt":40}})

db.account.find({"age":{"$ne":30}})

$in查询:db.account.find({"age":{"$in":[30,32]}})

db.account.find({"age":{"$nin":[30,32]}})

$or 或查询,可多键值或查询:db.account.find({"$or":[{"userName":"bbs2000000"},{"age":32}]})

组合查询db.account.find({"$or":[{"userName":"bbs2000000"},{"age":{"$in":[30,32]}}]})

$not运算符,可运用于任何条件之上,表示取非:db.account.find({"age":{"$not":{"$nin":[30,32]}}})

$mod模运算:db.account.find({"age":{"$mod":[5,0]}})

=====================查询========高级查询规则-null=================

null不仅匹配自身,还匹配不存在db.account.find({"createTime":null})

要结合$exist才能准确查出属性为null的文档:

db.account.find({"createTime":{"$in":[null],"$exists":true}})

====================查询=======正则表达式==================

正则表达式规则遵循javascript正则表达式规则db.account.find({"userName":/bbs200000/i})

带前缀正则表达式查询性能最好:db.account.find({"userName":/^bbs200000/i})

=====================查询========查询数组==================

db.food.insert({"_id":1,"fruit":["apple","banana","peach"]})

db.food.insert({"_id":2,"fruit":["apple","watermelon","orange"]})

db.food.insert({"_id":3,"fruit":["cherry","banana","apple"]})

单元素匹配任何一个就行:db.food.find({"fruit":"apple"})

多元素匹配要用$all,既有apple又有banana的文档:

db.food.find({"fruit":{$all:["apple","banana"]}})

数组下标从0开始,用数组下标指定位置查询:

db.food.find({"fruit.2":"apple"})

$size,查询指定数组长度的数组:db.food.find({"fruit":{"$size":3}})

=====================查询========查询内嵌文档==================

db.account.insert({"userName":{"first":"joe","last":"schmoe"},"age":35})

完全匹配查询:db.account.find({"userName":{"first":"joe","last":"schmoe"}})

改变文档数据模式db.account.update({},{"$set":{"userName.passwd":"ddd"}})

点表示法查询(不受文档数据模式改变影响):db.account.find({"userName.first":"joe","userName.last":"schmoe"})

再次改变文档数据模式,增加数组元素db.account.update({},{"$push":{"comments":{"author":"joe","score":3,"comment":"test"}}})

db.account.update({},{"$push":{"comments":{"author":"tom","score":5,"comment":"test"}}})

查询作者为joe并且得分超过5分的文档:db.account.find({"comments.author":"joe","comments.score":{"$gte":5}})

正确做法,采用$elemMatch对内嵌文档多键匹配:db.account.find({"comments":{"$elemMatch":{"author":"joe","score":{"$gte":5}}}})

=====================查询========where查询==================

db.food.insert({"apple":1,"banana":6,"peach":3})

db.food.insert({"apple":8,"spinach":4,"watermelon":4})

db.food.find({"$where":function(){ for(var current in this){ for(var other in this){ if(current !=other && this[current]==this[other]){ return true; } } } return false; }});

不是逼急了不要用where 查询,能用键/值对尽量用键/值对查询方式

where查询无法使用索引,并且文档要从bson转成javascript对象,查询速度非常慢

=====================查询========游标操作==================

for(i=0;i<100;i++){ db.c.insert({x:i}); }

定义游标,不会立即执行查询:var cursor=db.c.find()

游标迭代器:while(cursor.hasNext()){ obj=cursor.next() }

执行cursor.hasNext()时,查询发往服务器,执行真正查询,shell会获取前100个结果或者4M数据(两者较小者)返回。

限制结果数据:db.c.find().limit(5);

跳过匹配文档:db.c.find().skip(5);

排序:sort用一个对象为参数,键、值对表示,键对应文档键名,值表示排序方向。1-升序,-1 - 降序。

db.c.find().sort({x:-1}) db.c.find().sort({x:1})

多键复合排序:db.account.find().sort({userName:1,age:-1})

=====================查询========游标分页==================

for(i=0;i<100;i++){ db.c.insert({x:i,y:"post"}); }

按条件查询每页20条纪录db.c.find({"y":"post"}).limit(20).sort({"x":1})

db.c.find({"y":"post"}).limit(20).sort({"x":-1})

分页参数就是skip的参数db.c.find({"y":"post"}).limit(20).skip(20).sort({"x":1})

注意,用skip跳过少量文档是可行的,数量太多就会变慢

另一种不用skip进行分页的方法

=====================查询========游标内幕==================

服务器端,游标消耗内存和其它资源,要尽快合理释放

游标遍历完或客户端发消息终止,释放游标

游标在客户端不在作用域,驱动会向服务器发消息销毁游标

超时销毁机制,游标即使是在客户端作用域内,但10分钟不用,也会自动被销毁

若关闭游标超时销毁机制(驱动immortal函数),游标使用完,一定要显式将其关闭,否则其会一直消耗服务器资源。

====================索引创建==================

for(i=0;i<10000;i++){ db.account.insert({userName:"bbs"+i,age:i%60,createTime:new Date()}); }

单键索引:db.account.ensureIndex({"userName":1})

1--表示升序,-1 -- 表示降序

复合索引:db.account.ensureIndex({"userName":1,"age":-1})

db.account.ensureIndex({"userName":1,"age":1,"createTime":1})

只有索引前部的查询会得到优化

索引优化查询的同时,会对增删改带来额外开销

索引创建原则

应用程序会做什么查询,哪些键需要索引

每个键的索引方向是怎样的

如何应对扩展?如何通过不同键的排列使数据尽可能多的保存在内存中,增加命中率

数据量大时为排序创建索引

=====================唯一索引=================

db.account.ensureIndex({"userName":1},{"unique":true})

默认插入数据时不检查数据唯一性

安全插入时才会检查数据唯一性

_id键索引就是唯一索引,并且不能删除

也可创建唯一复合索引,单键可重复,组合后不相同即可

=====================查询分析工具==================

explain可分析查询使用索引的情况,耗时、及扫描文档数的统计

db.account.find({"userName":"bbs22"}).explain()

db.account.find({"age":30}).sort({"userName":1}).explain()

db.account.find({"age":{$gt:20,$lt:30}}).explain()索引前后比较

=====================强制指定索引使用==================

hint可以强制mongodb使用某一个索引

db.account.find({"age":{$gt:20,$lt:30}}).hint({"userName":1,"age":1,"createTime":1}).explain()

通常mongodb会智能选择最优索引使用

=====================聚合统计==================

count

统计集合总数: db.account.count()

条件统计:db.account.count({"age":30})

增加查询条件统计通常用于分页查询,但增加查询条件统计会使统计变慢

distinct

用于找出指定键的不同值

db.runCommand({"distinct":"account","key":"age"})

必须指定集合名,键名

计算distinct后的count总数:

db.runCommand({"distinct":"account","key":"age"}).values.length

db.runCommand({"distinct":"account","key":"age","query":{"age":{"$gt":30}}}).values.length

group

db.account.group({ key:{"age":true}, initial:{number:0}, reduce:function(doc,prev){prev.number+=1 },cond:{"age":{"$gt":30}}})

key关键字标识我们想要汇总的数据(类似于SQL中GROUP BY子句的参数)

initial关键字标识我们记录的关键字的关键值的初始值

reduce关键字定义了一个方法,每次遇一个文档要做的事情

cond关键字定义条件

========================高级指南==================命令的工作原理================

db.account.drop()

db.runCommand({"drop":"account"})

命令响应结果是一个文档,ok键值为true表示执行成功,为false表示执行失败。

errmsg键值表示失败原因。

MongoDB中的命令其实是作为一种特殊类型的查询来执行的。这些查询针对$cmd集合来执行,runCommand仅仅命令文档,执行等价查询。

db.$cmd.findOne({"drop":"c"})

支持的命令浏览

db.listCommands()

访问web console也可获取

版本命令:db.runCommand({"buildInfo":1})

集合统计信息 :db.runCommand({"collStats":"account"})

修复数据库:{"repairDatabase":1} 比较耗时

删除集合:{"drop":collection}

查看对本集合最后一次操作的错误信息:db.runCommand({ "getlasterror" : 1 , "w" : 1 , "wtimeout" : 0})

删除当前数据库:{"dropDatabase":1}

删除索引:{"dropIndexes":collection,"index":name}

检查本服务器是主服务器还是从服务器:{"isMaster":1}

列出服务器上所有数据库(管理专用):{"listDatabases":1}

重命令集合:{"renameCollection":a,"to":b} a、b均必须为完整的命令空间(管理专用)

服务器管理统计信息:{"serverStatus":1}

========================高级指南==================固定集合================

固定集合:事先创建,大小固定

类似环状队列,空间不足队列头文件被替换

不能手工删除文档,只能自动替换

特点;插入性能好,不需额外分配空间,直接插入队列尾.按插入顺利查询速度极快

创建固定大小100k的固定集合:db.createCollection("fixed",{capped:true,size:100000})

插入测试数据:for(i=0;i<10000;i++){ db.fixed.insert({userName:"bbs"+i,age:i%60,createTime:new Date()}); }

创建固定大小100K且文档数最大100的固定集合: db.createCollection("fixed",{capped:true,size:100000,max:100})

容量未满时按文档数限制,容量满时按容量限制

转换语法:db.runCommand({convertToCapped:"account",size:10000})

========================高级指南==================GridFS================

GridFS是MongoDB中存储大二进制文件的机制。

使用GridFS后不需要再使用单独的文件存储架构

可直接利用MongoDB的复制分片机制,使文件存储也具有水平扩展、故障恢复功能

不产生磁盘碎片,因为MongoDB分配数据文件空间时以2GB为一块

GridFS用法:

./mongofiles -d bbs put test.txt

./mongofiles -d bbs get test.txt

./mongofiles -d bbs delete test.txt

./mongofiles -d bbs search test

./mongofiles -d bbs list

GridFS是建立在MongoDB文档规范基础上的轻量级文件存储规范

将大文件分块,每块独立存储

db.fs.chunks.find()

db.fs.files.find()

========================高级指南=================服务端脚本================

db.eval可在MongoDB服务端执行javascript脚本。

db.eval("return 1;")

db.eval("function() {return 1;}")

参数传递:

db.eval("function(u) { print('hello,'+u+'!');}",["user1"])

========================高级指南=================服务端脚本================存储javascript:

system.js保存javascript变量及代码

db.system.js.insert({"_id":"x","value":1})

db.system.js.insert({"_id":"y","value":2})

db.system.js.insert({"_id":"z","value":3})

db.eval中可引用变量:db.eval("function() {return x+y+z;}")

========================高级指南=================服务端脚本================写一个类似log4j的日志函数:

db.system.js.insert({"_id":"log","value": function(msg,level){ var levels=["DEBUG","WARN","ERROR","FATAL"]; level =level?level:0; var now=new Date(); print(now+" "+levels[level]+msg); }})

使用示例:db.eval("x=1;log(' x is '+x);x=2;log(' x is greater than 1',1);")

db.eval("log('refactor log test',2)")

========================高级指南=================服务端脚本================DBRef数据库引用:

DBRef指向一个集合的一个文档引用

类似表关联

{"ref":collection,"$id":id_value,"$db":database}

DBRef不是必须用,通常会引入复杂性让人误解。可有其它方式建立关联。

=======================高级指南=================系统管理高级技巧-系统监控=================

MongoDB持久化配置 :

持久化配置

journal=true

journalCommitInterval=100

正确关闭MongoDB

./mongod --shutdown或./mongod -f ../etc/mongo.conf --shutdown

不能直接kill进程,否则可能造成库文件损坏

=======================高级指南=================系统管理高级技巧-系统监控=================监控serverStatus

db.runCommand({"serverStatus":1})

参数含义简介:

"globalLock" : {

"totalTime" : NumberLong("511789041000"),--自实例启动全局锁创建以来到现在多长时间,单位微秒.

"lockTime" : NumberLong(105416165),--自全局锁创建以来锁定总时间,单位微秒

"currentQueue" : {

"total" : 0,--等待全局锁的队列中操作数目

"readers" : 0,--等待读锁的队列中操作数目

"writers" : 0--等待写锁的队列中操作数目

},

"activeClients" : {

"total" : 0,--连接到server的当前活动client数目

"readers" : 0, --执行读操作的当前活动client数目

"writers" : 0--执行写操作的当前活动client数目

}

},

"mem" : {

"bits" : 64,--64位机器

"resident" : 31,--占用物理内存量

"virtual" : 20478, --占用的虚拟内存量

"supported" : true, --是否支持扩展内存

"mapped" : 10188, --映射到内存的数据文件大小,很接近于你的所有数据库大小。

"mappedWithJournal" : 20376

},

"connections" : {

"current" : 1,--当前活动连接量。连接到server的当前活跃连接数目

"available" : 19999--剩余空闲连接量。剩余的可用连接数目

},

"backgroundFlushing" : {

"flushes" : 8527, --数据库刷新写到磁盘的次数

"total_ms" : 599904,--数据库刷新数据到磁盘花费的微秒数

"average_ms" : 70.35346546264806,--执行单次刷新花费的平均微秒数

"last_ms" : 51,--最后一次执行完成刷新数据到磁盘花费的微秒数

"last_finished" : ISODate("2012-12-26T00:41:32.013Z")-当最后一次刷新数据完成时的时间戳

},

"cursors" : {

"totalOpen" : 0, --server为client保持的游标(cursor)总数

"clientCursors_size" : 0,

"timedOut" : 0--server启动以来游标(cursor)超时的总数

},

"network" : {

"bytesIn" : 1925,--发送到数据库的数据总量(bytes)

"bytesOut" : 4294,--数据库发出的数据总量(bytes)

"numRequests" : 24--发送到数据库的请求量

},



"opcounters" : {

"insert" : 0, --server启动以来总的insert数据量

"query" : 16646, --server启动以来总的query数据量

"update" : 1,--server启动以来总的update数据量

"delete" : 0, --server启动以来总的delete数据量

"getmore" : 0, --server启动以来调用任何游标的getMore总次数

"command" : 22 --server启动以来执行其他命令的总次数

},

"asserts" : {

"regular" : 0, --server启动以来抛出正规断言(assert 类似于异常处理的形式)总数目

"warning" : 0,--server启动以来抛出的告警总数目

"msg" : 0,--消息断言数目。服务器内部定义的良好字符串错误

"user" : 0, --用户断言数目。用户产生的错误,譬如:磁盘空间满;重复键。

"rollovers" : 0--server启动以来,assert counters have rolled over的次数

},



"writeBacksQueued" : false,--是否有从mongos执行的retry操作

"dur" : {

"commits" : 29,--上一间隔journal日志发生commit的次数

"journaledMB" : 0,--上一间隔写到journal日志的数据量(单位:MB)

"writeToDataFilesMB" : 0,--上一间隔journal日志写到数据文件的数据量(单位:MB)

"compression" : 0,

"commitsInWriteLock" : 0, --写锁期间发生commits的次数

"earlyCommits" : 0,--schedule时间前请求commit的次数

"timeMs" : {

"dt" : 3004,

"prepLogBuffer" : 0,--准备写journal日志花费的时间

"writeToJournal" : 0,--写journal日志花费的实际时间

"writeToDataFiles" : 0,--journal日志后写数据文件花费的时间

"remapPrivateView" : 0

}

},

=======================高级指南=================系统管理高级技巧-系统监控=================监控mongostat

mongostat是mongdb自带的状态检测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出

insert: 一秒内的插入数

query : 一秒内的查询数

update: 一秒内的更新数

delete: 一秒内的删除数

getmore: 查询时游标(cursor)的getmore操作

command: 一秒内执行的命令数

flushes: 一秒内flush的次数

mapped 所有的被mmap的数据量,单位M

vsize 虚拟内存使用量,单位M

res 物理内存使用量,单位M

faults/s 每秒访问失败数(只有Linux有),数据被交换出物理内存,放到swap。不要超过100,否则就是机器内存太小,造成频繁swap写入。此时要升级内存或者扩展

locked % 被锁的时间百分比,不要太大

idx miss: 索引不命中所占百分比。如果太高的话就要考虑索引是不是少了

qr|qw:客户端查询等待数

ar|aw:客户端文档读写等待数,都为0的话表示mongo毫无压力。高并发时,一般队列值会升高

netIn|netOut:网络带宽压力

conn 当前连接数

time 时间戳

=======================高级指南=================系统管理高级技巧-系统监控=================MongoDB安全

默认没有设置安全认证

增加root用户:

use admin

db.addUser("root","rootabc")

给自定义库增加用户:

use bbs

db.addUser("readwrite","rw")

db.addUser("read","readabc")

增加配置项auth=true,打开库安全认证

db.auth("root","rootabc")

用户存放在数据库的system.users集合中。

use test

db.auth("read","readabc")

=======================高级指南=================系统管理高级技巧-系统监控=================备份恢复

mongodump -h dbhost -d dbname -o dbdirectory -- 数据库备份

mongorestore -h dbhost -d dbname --directoryperdb dbdirectory -- 数据库恢复

可在线实时备份

提取快照方法:db.runCommand({"fsync":1,"lock":1})

fsync强制所有缓冲区写入磁盘

备份完后解锁:db.fsyncUnlock()

缺点:耽误读写操作

=======================高级指南=================系统管理高级技巧-系统监控=================数据库修复

mongod --repair启数据库修复

或db.repairDatabase()

修复原理:将所有文档导出并马上导入,忽略无效文档,然后重建索引

修复会化点时间

=======================高级指南=================复制功能=================

复制优点

数据备份

数据恢复

读写分离

主、从节点建立:

建立启动主节点:./mongod -f ../etc/mongo.conf --master,注意--master表示主节点,可跟--port表明启动端口

建立从节点: mkdir /data/slave,启动从节点: ./mongod --dbpath /data/slave --port 10001 --slave --source localhost:27017,

注意端口必须与主节点不同,--source指明主节点

ps:一个主节点挂载从节点不超过12个

复制管理

打印主从复制集群情况:

主节点上

db.printReplicationInfo()

configured oplog size日志大小

oplog first event time日志什么时候开始记录

oplog last event time日志最后一条记录时间

从节点上

source 主节点地址

syncedTo 最后一次同步时间

日志大小调节

./mongod -f 启动配置文件路径 --oplogSize(log大小调节参数) xxxxx(值)

=======================高级指南================MongoDB数据文件内部结构=================



MongoDB数据文件内部结构

MongoDB在数据存储上按命名空间来划分,一个Collection是一个命名空间,一个索引也是一个命名空间。

同一个命名空间的数据被分成很多个Extent,Extent之间使用双向链表连接。

在每一个Extent中,保存了具体每一行的数据,这些数据也是通过双向链接来连接的。

每一行数据存储空间不仅包括数据占用空间,还可能包含一部分附加空间,这使得在数据Update变大后可以不移动位置。

索引以BTree结构实现

=======================高级指南================副本集数据同步机制=================



红色箭头表示写操作可以写到Primary上,然后异步同步到多个Secondary上。

蓝色箭头表示读操作可以从Primary或Secondary任意一个中读取。

各个Primary与Secondary之间一直保持心跳同步检测,用于判断Replica Sets的状态

=======================高级指南=================副本集=================

概念:

副本集是具有故障恢复功能的主从集群

与主从集群区别:副本集没有固定主节点

本质上是很牛X的具有HA功能的主从集群

副本集创建:

为副本集取名 (jm)

./mongod --dbpath /data/db1 --port 1111 --replSet jm

./mongod --dbpath /data/db1 --port 2222 --replSet jm

./mongod --dbpath /data/db1 --port 3333 --replSet jm

--replSet参数,创建副本集中一个节点

创建启动副本集中第二个节点

副本集初始化,初始化命令只能执行一次

config_jm={"_id":"jm",members:[{_id:0,host:"192.168.154.133:1111"},{_id:1,host:"192.168.154.143:2222"},{_id:2,host:"192.168.154.153:3333"}]}

rs.initiate(config_jm)

查看副本集状态:

rs.status()

db.isMaster()

副本集故障恢复:

副本集任何时间只有一个活跃节点

投票机制决定谁成为活跃节点,优先级最高、数据最新的节点获胜

节点类型:

standard:这种是常规节点,他存储一份完整的数据库副本,参与选举投票,有可能成为活动节点

passive:存储一份完整的数据库副本,参与选举投票,不能成为活动节点

arbiter:仲裁者只参与投票,不接收复制的数据,也不能成为活动节点

ps:注意一点:副本至少3个,因为2个的话有一个挂了另外一个不能投票了! 剩下一个会一直是secondary

=======================高级指南=================分片=================

概念:

分片是指将数据拆分,将其分散到不同机器上的过程

mongodb支持自动分片

何时分片:磁盘不够用了、单个mongd不能满足写数据性能要求、想将大量数据放在内存中提高性能

片键指从集合中挑选一个键,该键值做为数据拆分的依据

创建分片步骤:

选择合适的片键(eg:username)

1 :建立mongodb启动配置mongo.conf文件

logpath=../log/mongodb.log

dbpath=/home/tom/data/dbfp

logappend=false

cpu=false

journal=true

journalCommitInterval=100

rest=true

fork=true

auth=false

2 :启动mongodb

./mongod -f ../etc/mongo1.conf --port 27017

./mongod -f ../etc/mongo2.conf --port 27018

3 : 启动配置服务器

./mongod -f ../etc/mongoconf.conf --port 20000

4 : 启动mongos

./mongos --port 30000 --configdb 配置服务器IP:20000

5 : 配置分片节点

./mongo mongos服务器IP:30000/admin

db.runCommand({addshard:"分片服务器1:27017",allowLocal:true})

db.runCommand({addshard:"分片服务器2:27018",allowLocal:true})

6 : 启动分片

db.runCommand({"enablesharding":"jmtest"})

7 : 在指定列上建立片键

db.runCommand({"shardcollection":"jmtest.account","key":{"userName",1}}) 1表示升序

db.jmtest.getIndexs() 查看索引

8 : 查看各分片状态

登录mongos服务器

./mongo mongos服务器IP:30000/admin

db.printShardingStatus()

以上操作都会保存到配置服务器里面

生产配置:

三个配置服务器

多个mongos服务器

每个片都是副本集

生产环境应建立3个配置服务器

关于分片的其他操作如:删除,请查阅另一篇文章:http://blog.csdn.net/johnstrive/article/details/24690805

=======================高级指南=================分片机制=================



MongoDB的分片是指定一个分片key来进行,数据按范围分成不同的chunk,每个chunk的大小有限制。

有多个分片节点保存这些chunk,每个节点保存一部分的chunk。

每一个分片节点都是一个Replica Sets,这样保证数据的安全性。

当一个chunk超过其限制的最大体积时,会分裂成两个小的chunk。

当chunk在分片节点中分布不均衡时,会引发chunk迁移操作。



客户端访问路由节点mongos来进行数据读写。

config服务器保存了两个映射关系,一个是key值的区间对应哪一个chunk的映射关系,另一个是chunk存在哪一个分片节点的映射关系。

路由节点通过config服务器获取数据信息,通过这些信息,找到真正存放数据的分片节点进行对应操作。

路由节点还会在写操作时判断当前chunk是否超出限定大小。如果超出,就分列成两个chunk。

对于按分片key进行的查询和update操作来说,路由节点会查到具体的chunk然后再进行相关的工作。

对于不按分片key进行的查询和update操作来说,mongos会对所有下属节点发送请求然后再对返回结果进行合并。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: