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

MongoDB find getmore操作慢问题排查 本文介绍一次帮助业务排查线上查询操作慢的问题的详细过程以及解决方法。 阅读详情
./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.youkuaiyun.com/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会对所有下属节点发送请求然后再对返回结果进行合并。
渗透测试入门:从零构建安全攻防思维与实战能力 渗透测试作为信息安全领域的核心实践,本质是模拟攻击者行为以发现系统安全漏洞的授权评估活动。其技术原理建立在扎实的计算机基础、网络协议和Web技术栈理解之上,通过信息收集、漏洞扫描、利用与权限提升等标准化流程,实现对目标系统的深度安全评估。掌握渗透测试不仅能够帮助企业识别和修复安全风险,提升整体安全防护水平,更在网络安全人才培养、红蓝对抗演练等场景中具有重要价值。本文以渗透测试入门为核心,系统梳理了从环境搭建、工具使用到实战方法论的学习路径,并融入靶场实战与DC-1通关思路,为初学者提供了一套可操作的成长框架 阅读详情

相关推荐

Node.js+Express+MongoDB博客系统全栈开发实战指南

在Web开发中,Node.js以事件驱动和非阻塞I/O模型成为构建高并发I/O密集型应用的首选,Express作为其生态中最成熟的轻量级框架,通过灵活的中间件机制简化了路由与请求处理;而MongoDB文档型数据库的JSON式存储方式,恰好与JavaScript对象无缝衔接,让数据建模更贴近业务逻辑。三者组合为博客管理系统这类内容型应用提供了高效、可扩展的技术底座。本文从环境配置、npm脚本权限排查等易踩坑环节入手,深入讲解Mongoose Schema设计、JWT身份认证、RESTful API规范、聚合管

weixin_34184561的博客 414

mongodb快速入门

mongodb介绍MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种。它在许多场景下可用于替代传统的关系型数据库或键/值存储方式。Mongo使用C++开发。Mongo的官方网站地址是://www.mongodb.org/NoSql,全称是 Not Only Sql,指的是非关系型的数据库。下一代数据库主要解决几个要点:非关系型的、分布式的、开源的、水平可...

weixin_33851429的博客 255

mongodb项目实战(初战)源代码

玩转mongodb(三):mongodb项目实战(初战)源代码

mongodb的监控与性能优化

一.mongodb的监控 mongostat是mongdb自带的状态检测工具,在命令行下使用。它会间隔固定时间获取mongodb的当前运行状态,并输出。如果你发现数据库突然变慢或者有其他问题的话,你第一手的操作就考虑采用mongostat来查看mongo的状态。 它的输出有以下几列: inserts/s 每秒插入次数 query/s 每秒查询次数 update

服务器端攻城师 1213

Jlink除了调试还能干啥?用JFlash SPI给W25Q64烧录固件的5个实用技巧

本文深入探讨了Jlink的隐藏功能,特别是通过JFlash SPI高效烧录W25Q64的5个进阶技巧。从硬件连接优化到批量处理脚本,再到数据安全验证,这些技巧能显著提升烧录速度和稳定性,适用于量产环境。文章还提供了详细的参数配置和脚本示例,帮助工程师充分发挥Jlink的潜力。

weixin_29164843的博客 408

Microchip Studio 7.0 从下载到项目调试:AVR开发者的完整入门指南(附常见问题解决)

本文为AVR开发者提供了Microchip Studio 7.0从下载安装到项目调试的完整入门指南。详细介绍了如何获取安装包、创建第一个AVR工程项目,并配置编译与调试环境。同时,文章重点解决了开发过程中常见的编译错误和仿真问题,帮助开发者快速上手并高效使用这一官方集成开发环境。

joy55的博客 333

mongoDB学习笔记

一.为什么选择mongoDB 开源的NoSql数据库。 1.无数据结构限制:没有表结构概念,不需要事先定义表结构就可以使用,每条记录可以有完全不同结构。 2.完全的索引支持 3.方便的冗余与扩展:复制集保证数据安全,分片扩展数据规模。 4.良好的支持:完善的文档,齐全的驱动支持。 二.mongoDB安装与配置 1.mongoDB运行环境 mong

happydream_C的博客 1347

EEGLAB安装、EDF数据导入、EEG预处理(Matlab)

目录下载和安装下载安装遇到问题及解决方案导入EDF数据EEG预处理 下载和安装 下载 链接:https://pan.baidu.com/s/17eMT6B7LgZ4PyqWvD5ixmg 提取码:12gz 安装 **第一步:**将下载下来的文件解压,修改名称为eeglab,将此文件夹存放在matlab的安装目录里的toolbox文件夹下,下图是我的路径,需要拷贝到自己相对应的路径中 第二步: 打开Matlab软件,点击主页中的设置路径 设置路径 点击添加并包含子文件夹,将eeglab文件夹添加进来,保

y18771025420的博客 1万+

MongoDB 中的锁分析

MongoDB 是一种常见的文档型数据库,因为其高性能、高可用、高扩展性等特点,被广泛应用于各种场景。在多线程的访问下,可能会出现多线程同时操作一个集合的情况,进而出现数据冲突的情况,为了保证数据的一致性,MongoDB 采用了锁机制来保证数据的一致性。下面来看看 MongoDB 中的锁机制。1、MongoDB 中使用一个 readers-writer 锁,它允许并发多个读操作访问数据库,但是只提供唯一写操作访问;

snowyar的专栏 1973

(Cascade extended state observer)级联ADRC的simulink仿真和程序---送给中国研究学者的精华版

(Cascade extended state observer)级联ADRC的simulink仿真和程序---送给中国研究学者的精华版

weixin_44312889的博客 3778

半导体AMHS天车振动控制:从0.5G到超低振动的技术演进与工程实战

在先进晶圆厂中,自动化物料搬运系统(AMHS)的天车如同空中出租车,承担着晶圆盒(FOUP)在洁净室各工艺区间的转运任务。然而,当天车加减速、过弯或抓取时产生的机械振动通过轨道梁和建筑结构传递至光刻机等敏感设备,便可能直接威胁套刻精度与良率。传统被动减振方案依靠橡胶垫和弹簧,在0.5G指标时代曾行之有效,但在EUV光刻和先进制程面前已力不从心。主动振动控制技术通过传感器、控制器与作动器构成的闭环系统,在轨道吊点和机械手端实时输出反向力抵消振动,配合磁悬浮走行、轻量化结构及调度系统的路径优化,将振动从0.5G

weixin_29188043的博客 341

MongoDB基础入门003--使用官方驱动操作mongo,C#

本篇先简单介绍一下,使用官方驱动来操作MongoDB。至于MongoDB原生的增删改查语句,且等以后再慢慢学习。 一、操作MongoDB的驱动主要有两个   1.官方驱动:https://github.com/mongodb/mongo-csharp-driver/downloads,更新的还是比较及时的,目前已经支持大部门linq语法。   2.samus驱动:https://g...

diankaoli4837的博客 236

UE4免费资产库新玩法:Quixel Bridge插件安装与Megascans资源导入全攻略

本文详细介绍了如何在UE4中安装Quixel Bridge插件并导入Megascans资源,帮助开发者快速获取高质量3D资产。通过分步教程和实用技巧,提升游戏或影视场景的制作效率,特别适合需要真实感环境的项目。

weixin_27729671的博客 364

Mongodb数据库教程

一. mongodb的介绍: 1.NoSQL最常用的解释是非关系型的数据库 2.关系型数据库比如MySQL和非关系型数据库比如mongodb的区别: 关系数据库很强大,但是它并不能很好的应付所有的应用场景。 MySQL的扩展性差,大数据下IO压力大, 表结构更改困难 ...

小陈工的博客 378

RH850系列芯片深度剖析 1.5-链接(ld)文件解析

基础编译过程分为四个阶段:预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)、链接(Linking)。执行这四个阶段的程序(预处理器、编译器、汇编器、和链接器)一起构成了编译系统。CONSTANTS接下来的内存空间定义部分会使用这些常量来定义内存空间的范围,理论上来说不定义常量也没有影响,直接用魔鬼数字代替,定义常量的主要目的就是方便理解以及方便修改;从示例中可以看出,常量的值可以为16进制或者10十进制,而且10进制支持数量级单位(k级,M级);

本博客专注于嵌入式软件领域技术分享。 1427

三维点云转深度图

点云投影过程是将三维点云数据转化为二维图像坐标的关键步骤,它的实现涉及到相机内外参数的计算,包括相机的内部参数(如焦距和主点)和外部参数(如相机位置和方向)。具体来说,可以通过将每个点的三维坐标转换为相机坐标系下的坐标,然后使用相机内部参数和外部参数来计算在二维图像中的坐标。接着计算每个点的深度值,将深度值映射到像素值上,最后创建深度图像并将深度值赋给对应的像素值。这里需要注意的是,在将深度值映射到像素值上时,需要将像素值转换为 uchar 类型,否则在将深度值赋给像素值时会出现类型不匹配的错误。

点云兔子的博客 3171

MongoDB分片集群搭建

啥是分片 分片(sharding)是MongoDB用来将大型集合水平分割到不同服务器(或者复制集)上所采用的方法。不需要很强大的大型计算机就可以存储更多的数据,处理更大的负载 为啥要分片 存储容量需求超出单机磁盘容量 活跃的数据集超出单机内存容量,导致很多请求都要从磁盘读取数据,影响性能。 IOPS超出单个MongoDB节点的服务能力,随着数据的增长,单机实例的瓶颈会越来越明显 副本集具有节点数量限制 ps:垂直拓展vs水平拓展 垂直拓展:增加更多的cpu和存储资源来扩展容量 水平拓展:将数据集分布在多

蛋蛋的碎碎念 516

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

MongoDB安装运行

操作系统:osx 下载安装 1、官网下载 2、curl 命令来下载安装: # 进入 /usr/local cd /usr/local # 下载 sudo curl -O https://fastdl.mongodb.org/osx/mongodb-osx-x86_64-3.4.2.tgz # 解压 sudo tar -zxvf mongodb-osx-x86_64-3.4.2.tgz # 重...

weixin_33827965的博客 130

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

MongoDB数据库

1)ubuntu安装2)其他linux版本安装解压移动到/usr/local目录下将可执行文件添加到环境变量$PATH中启动/停止/重启查看是否启动成功配置文件位置默认端口号日志位置启动退出1)关于database命令2)关于集合命令

qq_62970331的博客 110

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

github管理工具_都在找MongoDB的可视化管理工具,我想你可以看看

背景这几天写过关于一些关于数据库工具方面的东西,但是由于知识欠缺,不能够兼顾到各种数据库,就像今天所要介绍的MongoDB 一样,因为很少接触到MongoDB ,对这方面的了解比较少,单纯的介绍工具,以后有机会在研究研究MongoDB ,但是有好的工具还是要分享出来的,至少能帮助一部分人了。介绍其实也是之前评论区看到有人咨询过MongDB的可视化管理工具,刚好我又知道两个,所以介绍下,一个是Nos...

weixin_39819283的博客 313

学习笔记:nodejs(二)——node+express+mongodb建站相关(express4)

昨天在慕课网上学习node+mongodb+express建站,中间遇到了很多问题,大部分是由于版本升级引起的。现在整理下。 node+express+mongodb   看到一个大神关于这三个货的简单介绍,现在直接拷贝过来用下~~~~(>_   node:是运行在服务器端的程序语言,表面上看过去就是javascript一样的东西,但是呢,确实就是服务器语言,个人觉得在一定层次上比c灵活,j

illuSioN4ng↖(^ω^)↗ 668

零基础入门漏洞挖掘:从核心技能到实战靶场的完整指南

漏洞挖掘是网络安全领域的核心技术之一,其本质是在软件、网络或协议中寻找可被利用的设计缺陷。理解其原理需要从基础入手,例如掌握HTTP/HTTPS等网络协议,它们是数据交互的基石,也是大多数Web漏洞产生的层面。从技术价值看,漏洞挖掘不仅能帮助发现潜在安全风险,更是提升系统防御能力、推动安全开发流程的关键实践。在应用场景上,这项技术广泛应用于渗透测试、代码审计和应急响应等领域。对于初学者而言,构建系统性知识框架至关重要,这包括掌握Burp Suite等工具进行流量分析,以及理解SQL注入、文件上传等常见漏洞的

weixin_33716154的博客 344

如何5分钟快速上手Mist CE:开源多云管理平台完整指南

想要统一管理AWS、Azure、Google Cloud等多个云平台?Mist CE开源多云管理平台让你在一个界面中轻松搞定!这个强大的云管理工具采用Docker Compose部署,只需简单几步就能启动运行,大大简化了多云环境的复杂性。 ## 🚀 快速上手体验:从零到一的部署之旅 ### 环境准备:检查系统配置 在开始之前,确保你的系统满足基本要求。Mist CE对硬件要求不高,但建议至

gitblog_01020的博客 1073

每日GitCode开源项目推荐:5个高效开发神器完整实战指南

项目名称核心优势推荐指数适合人群AtomCode终端轻量、多模型支持⭐️⭐️⭐️⭐️⭐️极客、后端开发、运维代码推理强、综合性能高⭐️⭐️⭐️⭐️⭐️需要私有化大模型的团队长文本处理、低显存占用⭐️⭐️⭐️⭐️文档分析、长流程任务GLM-5.1长程任务、自主规划⭐️⭐️⭐️⭐️⭐️自动化工程、全栈开发Kimi-K2.6多模态视觉、图文生成⭐️⭐️⭐️⭐️前端开发、数据分析师开源的力量就在于共享与进步。

热爱技术与前沿创新,深耕科技领域,在科创中精进自我;探索技术乐趣,分享技术干货与成长心得,以技术为伴,热爱生活,在科创与生活中双向成长。 485

Redis简介以及linux下常用命令

Remote Dictionary Server (redis) 是一个由salvatore Sanfilippo开发的高性能的key-value数据库(存储系统)。Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存也可持久化的日志型,key-value数据库,并提供多种语言的api。它通常被称为数据结构服务器,因为值可以是字符串(String)、哈希(Map)、列表(List)、集合(Set)、有序集合()等类型。

qq_39253096的博客 2349

给入门的小白整理的python爬虫学习路线指导参考

大家都知道,学习一门学科的时候是要清楚它的知识框架才能清晰的学习、有系统的学习,下面来列一列python网络爬虫的知识框架来帮助大家能够有效的学习和掌握,避免不必要的坑。 ps:文章来源于小编的头条号:“python数据科学频道”,想在手机端方便看文章的朋友可以去关注我的头条号。 python网络爬虫总的来说有五个大的方面: 前端知识——基础爬虫——框架爬虫——分布式爬虫——突破反爬虫 1.前...

小知的博客 1223
上一篇: Cannot convert value '0000-00-00 00:00:00' from column 1 to TIMESTAMP,url问题:对实体"*"的引用必须以 ';' 分隔符结尾
下一篇: 从mongodb移除分片
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值