mongo DB

一、安装
1、从mongodb官网下载mongodb,地址为:https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.9.tgz
将下载的包放到/opt目录下
cd /opt
wget -c https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.9.tgz
2、解压并重命名mongodb,然后创建db、logs目录分别用来存放数据和日志
tar zxvf mongodb-linux-x86_64-3.4.9.tgz
mv mongodb-linux-x86_64-3.4.9 mongodb
cd mongodb/
mkdir db logs
3、进入bin目录,编辑mongodb.conf配置文件
cd bin
vi mongodb.conf
mongodb.conf配置文件中参数解释
dbpath=/opt/mongodb/db #设置数据文件的存放目录
logpath=/opt/mongodb/logs/mongodb.log #设置日志文件的存放目录及日志文件名
nohttpinterface=true #关闭http端口,提高安全性
port=27017 #设置端口号(默认)
fork=true #设置为以守护进程的方式运行,即在后台运行
logappend:以追加方式写入日志,false:重新启动覆盖文件
replSet:指定复制集名称
oplogSize:操作日志文件的最大大小。单位为Mb,默认为硬盘剩余空间的5%
shardsvr:确定是否分片
profile:设置日志级别
#0 - 关闭性能分析,测试环境可以打开,生成环境关闭,对性能有很大影响;
#1 - 开启慢查询日志,执行时间大于100毫秒的语句
#2 - 开启所有操作日志
slowms:慢查询的时间设置
configdb:监听的配置服务器,只能有1个或者3个
configsvr:定义config server角色
chunkSize:单位 mb 生成环境请使用 100 或删除,删除后默认是64
maxConns:最大连接数,默认值:取决于系统(即的ulimit和文件描述符)限制,能设置该值大于2000

verbose=true:详细记录输出
objcheck=true:用于开发驱动程序是验证客户端请求
quota=true:启用数据库配额管理。默认false
oplog:设置oplog日志记录等级,默认0
0=off
1=w
2=r
3=both
7=w+some reads
nocursors=true:是否打开动态调试项
nohints=true:忽略查询提示
nohttpinteface=true:禁用http界面,默认为localhost:28017
noscripting=true:关闭服务器端脚本,这将极大限制功能,默认为false
notablescan=true:关闭扫描表,任何查询将会是扫描失败
nssize=(size):为新数据库指定.ns文件的大小,单位MB
mms-token = <token>:用于Mongo监控服务器的Accout token。
mms-name = <server-name>: Mongo监控服务器的服务器名称。
mms-interval = <seconds>: Mongo监控服务器的Ping间隔时间,即心跳
autoresync=true:默认为false,用于从实例设置,是否自动重新同步
sslOnNormalPorts=true:设置sll认证
opIdMem=(bytes)限制复制操作的内存使用
arbiter=server:port:仲裁服务器地址
- auth或noauth 是否已安全认证方式运行,默认是不认证的非安全方式
- cpu 启用定期记录cpu利用率和I/O等待
–master 指定为主机器

–slave 指定为从机器
- replSet 集群名

–source 指定主机器的IP地址

–pologSize 指定日志文件大小不超过64M.因为resync是非常操作量大且耗时,最好通过设置一个足够大的oplogSize来避免resync(默认的 oplog大小是空闲磁盘大小的5%)。
–journal 启用日志

–port 启用端口号

–fork 在后台运行

–only 指定只复制哪一个数据库

–slavedelay 指从复制检测的时间间隔

–auth 是否需要验证权限登录(用户名和密码)

–syncdelay 数据写入硬盘的时间(秒),0是不等待,直接写入
–notablescan 不允许表扫描

–pidfilepath 指定进程文件,不指定则不产生进程文件

–bind_ip 绑定IP,绑定后只能绑定的IP访问服务
- pidfilepath pid文件
keyFile 节点之间用于验证文件,内容必须保持一致,权限600,仅replica set模式有效
directoryperdb设置为true,修改数据目录模式,每个数据库的文件存储在dbpath指定的目录的不同文件夹中。注意:要是运行一段时间的数据库中,开启该参数,会导致原始的数据都会消失。因为数据目录都不同了,除非迁移现有的数据文件到它产生的数据库目
录中。
- noprealloc 预分配方式,默认false:使用预分配方式来保证写入性能的稳定,与分配在后台进行,并且每个与分配的文件都用0进行填充。这会让mong DB始终保持额外的空间和空余的数据文件,从而避免了数据增长过快而带来的分配磁盘空间引起的阻塞。设置为true来禁用预分配的数据文件,会缩短启动时间,但在正常操作过程中,可能导致性能显著下降。

4、做软连接
ln -s /opt/mongodb/bin/* /bin/
5、在bin目录下启动
mongod -f mongodb.conf
启动的三种方式;
./mongod --config mongodb.conf #以自定义的mongodb.conf配置文件启动
./mongod --repair -f mongodb.conf #已修复模式启动mongodb
./mongod --dbpath=/opt/mongodb/db --logpath=/opt/mongodb/logs/mongodb.log --fork #以参数启动
6、进入mongodb
./mongo
查看版本号
db.version()
7、配置开机自启动
vi /etc/rc.d/rc.local
/opt/mongodb/bin/mongod --config /opt/mongodb/bin/mongodb.conf
8、配置环境变量
vi /etc/profile
export MONGODB_HOME=/opt/mongdb/
export PATH=$MONGODB_HOME/bin:$PATH
source /etc/profile #重新加载环境变量
9、创建用户
创建管理员用户
use admin
db.createUser(
{
user:"wmon",
pwd:"123123",
roles:[{role:"root",db:"admin"}]
}

user表示用户名,pwd表示密码,role表示角色,db表示这个用户应用在哪个数据库上。用户的角色,有如下几种(参考资料):
角色名 备注
Read 允许用户读取指定数据库
readWrite 允许用户读写指定数据库
dbAdmin 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin 允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin 只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root 只在admin数据库中可用。超级账号,超级权限
db.dropUser('wmon') 删除用户
10、关闭mongodb服务(关闭数据库)
use admin
db.shutdownServer()
exit
使用db.shutdownServer()报错的解决方法:赋予hostManager权限
db.grantRolesToUser("admin",[{role:"hostManager",db:"admin"}])
或者关闭进程服务
mongod -f mongodb.conf --shutdown
11、重新启动新实例并开启权限认证
mongo DB默认是不开启权限认证的,开启认证:在配置文件mongodb.conf里加入auth=true或通过--auth参数启动
mongodb --config /opt/mongodb/bin/mongodb.conf --auth
登陆新用户
本地登录:mongo admin -u root -p 123123
远程登录:mongo 192.168.17.130:27017/admin -u root -p 123123
二、应用命令
1、单例命令
db #查看在那个数据库下
show dbs #查看所有数据库
show collections #查看库下有那些表(和show tables一样)
show users #显示当前所有用户
db.getUsers() #列出数据库的所有用户
db.stats(); #查询当前库的状态
db.表名.stats() #查询当前表的状态
db.version(); #当前的版本
db.表名.find() #查询该表的所有数据(一般默认显示20条,按it继续显示)
db.表名.findOne() #查询该表的第一条数据
use 库名 #创建一个数据库(若库名不存在,则会创建一个。如果不在此库做任何操作,则mongo DB会删除该数据库。)
db.getMongo(); #查看当前db的链接机器地址
db.currentOp() #获取当前的所有正在执行的查询
db.killOp(opid号) #强制停止正在执行的该查询
rs.stepDown() #对当前数据库进行降权
db.表名.remove({删除条件}) #删除表内一条数据
db.表名.drop() #清空表数据
db.dropDatabase() #删除库(在那个库下删除谁)
db.repairDatabase(); #修复当前数据库
db.getPrevError(); #查询之前的错误信息
db.resetError(); #清楚错误记录
db.表名.remove({删除条件}) #删除表内一条数据
db.表名.drop() #清空表数据
db.dropDatabase() #删除库(在那个库下删除谁)
db.repairDatabase(); #修复当前数据库
db.getPrevError(); #查询之前的错误信息
db.resetError(); #清楚错误记录
db.表名.insert({键值:“内容”}) #给指定数据库添加内容
db.表名.remove({删除条件}) #删除表内一条数据
db.表名.drop() #清空表数据
db.dropDatabase() #删除库(在那个库下删除谁)
db.repairDatabase(); #修复当前数据库
db.getPrevError(); #查询之前的错误信息
db.resetError(); #清楚错误记录
db.表名.find().count() #查询表的记录条数
Object.bsonsize(db.表名.find()) 查看表的大小
db.表名.totalSize() #查询表的总大小
db.表名.totalIndexSize() #查询所有索引的大小
db.表名.storageIndexSize() #查询分配到表空间大小
db.表名.ensureIndex({索引}) 添加索引
db.表名.getIndexes() 查询索引
db.表名.dropIndexes() 删除索引
db.表名.reIndex() 索引重建
db.表名.storageSize() 查看表当前可用的存储空间
db.表名.totalSize() 查看表分配的存储空间
db.shutdownServer() 终止服务进程
db.runCommand({fsunc:1,lock:1}) 为数据库写数据加锁
db.currentOp() 查看当前锁状态
db.$cmd.sys.unlock.findOne() 解锁
db.表名.count(可以加参数) 统计该表有几行文档
db.表名.distinct("age") 统计该表age的数据(不包括重复的)
db.php.find().skip(2),limit(3).sort({x:1}) #显示php表的第三行到第五行并按x排序{skip:第几条开始查询;limit:返回多少条数据;sort:排序}
db.cloneDatabase("ip:port"); #从指定主机克隆数据库
db.表名.ensureIndex({"username":1}) 创建索引(1表示username键的索引按升序存储,-1表示表示按降序)
db.表名.getIndexes() 查看索引是否建立
db.表名.dropIndex({"username":1}) 删除索引
db.表名.ensureIndex({"userid":1},{"unique":true}) 创建唯一索引
db.addUser("name",”pwd“,true); #添加用户,设置密码,是否只读
db.表名.find().sort((键值:+1)); #按键值(升序+或降序-)排列
db.getCollection('原表名').renameCollection('新表名') #修改表名
db.原表名.renameCollection('新表名') #修改表名
db.表名.find({name:/^mongo/}) #查询表中name以mongo开头的数据
db.表名.update.({x:1},{$set:{x:999}}) #只修改x的数据,其他属性不变
db.表名.update({x:1},{$set:{x:999}},true) #如果查找的数据不存在,则自动写入一条
db.表名.update({x:1},{$set:{x:999}},false,true) #更新多条数据
db.表名.update({查询条件},{$set:{更新内容}}) #更新一条数据
db.users.update({age:25},{$set:{name:'changename'}},false,true); #修改age=25这行的name为changename
db.serverStatus().connections #查看mongo DB连接数
current 表示当前实力上正在运行的连接数
available 表示当前实例还可以支持的并发连接数
totalcreated 表示当前视力从启动到现在一共创建的连接数,包括历史已经关闭了的
mongod最大连接数是由maxConns(默认65536,可以在配置文件里设置)和操作系统单个进程能打开的最大文件描述符(可通过/etc/security/limits.conf文件来配置)总量的80%决定的,去两个值的最小值。

循环添加数据
> for (var i =0; i < 30; i++) {
... db.users.save({name:"u_" + i, age: 22 + i, sex: i % 2});
... };

mongodump -h ip -u 用户 -p 密码 ---authenticationDatabase 库d 库名 -o 导出的路径 #备份数据库
mongorestore -d 库名 -c 导入的备份文件路径下的.bson文件 #根据备份文件恢复数据库
mongoexport -h 127.0.0.1 --port 20001 -uxxx -pxxx -d xxx -c mobileIndex -o XXX.txt 导出允许指定导出条件和字段

mongoimport -h 127.0.0.1 --port 20001 -uxxx -pxxx -d xxx -c mobileIndex --file XXX.txt 把XXX.txt导入指定的机器
db.copyDatabase("db","db1") 复制数据库db生成db1
db.runCommand({"cloneCollection":"库名.表名",“form”:"ip:port"}) 克隆集合

2、集群命令

sh.status() 查看分片状态
db.printCollectionStats() 打印各表的状态信息
db.printShardingStatus() 打印分片状态信息
db.runCommand({addshard:"rs1/ip-1:port,ip-2:port,ip-3:port"}) 添加复制集分片
db.runCommand({removeShard:"shard3"}) 在mongos执行移除shard3分片
db.runCommand("flushRouterconfig") 在mongos执行刷新mongos配置信息
db.users.stats() 查看users表的集群状态
health表示副本集中该节点是否正常,0表示不正常,1表示正常;
state表示节点的身份,0表示非主节点,1表示主节点;
stateStr用于对节点身份进行字符描述,PRIMARY表示主节点,SECONDARY表示副节点;name是副本集节点的ip和端口信息
db.stats() 查询集群的成员的集合数量、索引数量等相关数据
db.status() 检查复制集成员状态
rs.add(“ip:port”) 添加复制集成员
rs.remove (“ip:port”) 移除复制集成员
db.runCommand({serverStatus:1}) 查看操作数量、内存使用、网络io等
db.setProfilingLevel(级别,时间) 设置慢查询
db.getProfilingLevel() 查看慢查询级别
db.printReplicationInfo() 可以打印第一次同步时间,最后一次同步时间和当前时间
db.system.profile.find({ns:'dbname.collectionname'}).limit(10).sort({ts:-1}).pretty(); 针对某库某表查询慢查询日志并按表格逆序显示
db.currentOp("active":true,"secs_running":{"$gt":2000}) 查看执行操作时间大于等于2000秒的动作
db.adminCommand( { "getParameter": 1, "logLevel":1}); 设置日志级别参数
db.adminCommand( { "setParameter": 1, "wiredTigerEngineRuntimeConfig": "cache_size=4G"}); 设置缓存大小

db.runCommand({listshards:1}) 检查shards配置及状态
db.chunks.count() --需切换到配置数据库(config) 检查数据块的数量
db.currentOp(true).inprog.forEach(function(doc){if(doc.active==true&&doc.secs_running>200 ){printjson(doc)}}) 找出运行时间超过200ms的链接的ipid
rs.printReplicationInfo() 查看oplog状态
rs.printSlaveReplicationInfo() 查看复制延迟
db.runCommand({removeshard:"节点名"}) 不但可以开始移除shard;在移除过程中执行该命令可以查看数据迁移进度,remaining的值就表示数据迁移的进度;chunks代表还剩多少块数据需要被迁移。dbs的值代表还剩多少库需要设置新的大本营。
db.runCommand({movePrimary:"源库名",to"新库名"}) 为原库设置新的大本营

 

三、mongo DB集群
mongodb的集群搭建主要有三种:主从模式、replica set模式、sharding模式
主从模式现在用的较少;replica set模式应用最为广泛;sharding模式最为完备,但配置维护较为复杂。
(一)replica set即副本集方式主要两个目的,一个是数据冗余做故障恢复使用,当发生硬件故障或其他原因造成的宕机时,可以使用副本进行恢复。另一个是做读写分离,读的请求分流到副本上,减轻主的读压力。
replica set中的secondary节点默认是不可读写的。在写多读少的应用中,可以进行读写分离,由secondary来分但读的压力,primary只承担写操作。
有两种临时让secondary节点支持读:1、db.getMongo().setSlaveOk(); 2、rs.slaveOk();
永久让secondry支持读:1、 vi ~/.mongorc.js增加rs.slaveOk();
部署replica set节点必须为奇数,最少三台,包含三类角色:主节点(primary)、副本节点(secondary)、仲裁者(arbiter)
主节点:接受所有的写请求,然后把修改同步到所有secondary。默认读请求也是发到primary节点处理的,需要转发到secondary需要客户端修改一下连接配置。
副本节点:提供数据备份和读功能,可以被选为主节点。
仲裁者:该角色是可选的。不保有数据,不参与选主,只进行选主投票。使用arbiter可以减轻数据存储的硬件需求,应用于奇数的数据库时,在生产环境下它不要和其他节点部署在同一台机器上。
隐藏者:Secondary还有一些特殊的成员类型:Priority 0 #不能升为主,可以用于多数据中心场景;一般用作备份或统计报告用
缺点:每个节点都要存储一份完整的数据,当存储数据量越来越大的时候,只能通过扩大每个节点的容量来实现扩容。这种垂直扩容的方式容易达到极限,并且成本高。
1、在/opt下解压mongodb,创建数据目录
tar xf mongodb-Linux-x86-64-3.4.9.tgz -C /opt/
mv /opt/mongodb-linux-x86_64-3.4.9 /opt/mongodb
mkdir -p /opt/mongodb/db/master(slaver\arbiter)
mkdir -p /opt/mongodb/logs/
2、创建配置文件
主节点:vi /opt/mongodb_master.conf
#master.conf
dbpath=/opt/data/mongodb/master

logpath=/opt/mongodb/master.log

pidfilepath=/opt/mongodb/master.pid

#keyFile=/opt/mongodb/mongodb.key

directoryperdb=true

logappend=true
replSet=testrs
bind_ip=192.168.17.132
port=27017

#auth=true

oplogSize=10000

fork=true

noprealloc=true

#maxConns=4000
副本节点:vi /opt/mongodb_slaver.conf
#slave.conf
dbpath=/opt/data/mongodb/slaver

logpath=/opt/mongodb/slaver.log

pidfilepath=/opt/mongodb/slaver.pid

#keyFile=/opt/mongodb/mongodb.key

directoryperdb=true

logappend=true
replSet=testrs

bind_ip=192.168.17.131
port=27017

#auth=true

oplogSize=10000

fork=true

noprealloc=true

#maxConns=4000
仲裁点:vi /opt/mongodb_arbiter.conf
#arbiter.conf
dbpath=/opt/data/mongodb/arbiter
logpath=/opt/mongodb/arbiter.log

pidfilepath=/opt/mongodb/arbiter.pid

#keyFile=/opt/mongodb/mongodb.key

directoryperdb=true

logappend=true
replSet=testrs
bind_ip=192.168.17.130
port=27017
#auth=true

oplogSize=10000

fork=true

noprealloc=true

#maxConns=4000
3、启动mongodb
mongod -f master.conf
mongod -f slaver.conf
monfod -f arbiter.conf
4、在主节点进行配置
连接mongo DB
mongo 192.168.17.132:27017
不要启动arbiter,要不就会报错
配置集群
use admin
cfg={ _id:"testdb", members:[ {_id:0,host:'192.168.255.141:27017',priority:2}, {_id:1,host:'192.168.255.142:27017',priority:1}, {_id:2,host:'192.168.255.142:27017',arbiterOnly:true}] };
是集群cfg配置生效
rs.initiate(cfg) 查看是否生效
如果报错如下:"errmsg" : "No host described in new configuration 1 for replica set shard_a maps to this node",
这就查看配置文件是否和命令行一致,再一个查看ip是否正确。
rs.status()
5.增加安全认证机制keyfile
openssl rand -base64 745 > /opt/mongodb/mongdb.key #生成key
chmod 600 /opt/mongodb/mongodb.key #修改文件权限为600
(1)将该key值放到集群每个节点上,保持一致权限设置为600
(2)修改每个配置文件的keyfile参数
(3)主库配置用户
先创建管理员账户
db.createUser({user:"admin",pwd"123123",roles:[{role:"userAdminAnyDatabase",db:"admin"}]});
对管理员进行身份验证
use admin
db.auth("admin","123123")
(4)重启进入
pkill mongod
mongod -f mongodb.conf
mongo -u admin -p 123123
添加节点命令

添加secondary:rs.add({host: "192.168.255.141:27017", priority: 1 })

添加仲裁点:rs.addArb("192.168.255.142:27017")

移除节点:rs.remove({host: "192.168.255.141:27017"})
(二)sharding和replica set类似,都需要一个仲裁节点,但是sharding还需要配置节点和路由节点。
分片模式下可以将数据拆分成多个数据块,存储在不同的节点。当数据量变大是可以通过添加分片实现扩容。sharding模式将应用的数据访问操作分散到多个shard,每个shard只承担一部分请求。
(1)shards :存储节点,为了提高可用性和数据的一致性,通常每个shard是一个replica set结构。线上环境,至少2个shards,且每个shard都是replica set结构。
数据的分区根据“shard key”,对于每个需要shading的collection,都需要指定shard key(分片键),分片键必须是索引字段或者为组合索引的左前缀;mongodb根据分片健将数据分成多个chunks,并将他们均匀分布在多个shards节点上。目前mongodb支持两种分区
算法区间(range)分区和哈希(hash)分区;range分区的shard key必须是数字类型。
1)Range分区:首先shard key必须是数字类型,整个区间的上下边界分别为“正无穷大”、“负无穷大”,每个chunk覆盖一段子区间,即整体而言,任何shard key均会被某个特定的chunk所覆盖。区间均为作闭右开。每个区间均不会有重叠覆盖,且互相临近。当然
chunk并不是预先创建的,而是随着chunk数据的增大而不断split。
2)Hash分区:计算shard key的hash值(64位数字),并以此作为Range来分区,基本方式同1);Hash值具有很强的散列能力,通常不同的shard key具有不同的hash值(冲突是有限的),这种分区方式可以将document更加随机的分散在不同的chunks上。
Range分区更好的支持range查询,根据指定的shard key进行range查询,router可以很简单的判断出那些chunks覆盖此range,并将请求转发给特定的几个shards。不过当shard key是单调递增时,range分区会导致数据分布不均,因为在一定时间内,所有write请求
(读取最新数据的read请求)将会映射到一个shard上,即少数shards在某段时间内承载了系统的大部分请求。
Hash分区正好相反,即使是单调递增的shard key,它们的Hash值也有较大不同,因此这些数据将会比较随机的分散在多个chunks上,但是这引入了range查询的问题,临近的shard key可能分布在不同的chunks上甚至是shards上,这意味着range查询需要访问所有的
shards,特别是在有sort、limit等操作时。
mongos为数据库提供了平衡机制,可以对chunks进行分裂和迁移,最终动态平衡数据分布。
spliting:一个后台进程,用于避免chunk增长过大。当chunk超过指定的chunk size(默认为64M),就会对chunk进行分裂。
balancing:一个后台进程,用于管理chunks迁移。
(2)routers:路由节点,即mongos节点。mongos接受客户端请求,并根据路由规则转发给合适的shard,然后再将数据返回给客户端。他起到一个路由、转发的作用。sharding集群可以有多个mongos节点,可以均衡客户端请求。线上环境是随着cpplication节点部署。
routers:本身不保存任何用户数据,负责转发客户端的读写请求、对shard的结果进行收集归并、运行balancer进程、跟踪split等;通常我们在每个application节点上部署一个mongos,因为mongos占用内存极少,几乎不占用磁盘,它只需要消耗一定的内存、CPU用于处理数据
即可,此外这样部署application与mongos通信距离最短、效率较高。你可能想在applications与mongos之间搭建提个proxy或者负载均衡器,这种方式是很难实施的,而且可能会带来很多的问题,proxy需要能够对mongodb的数据protocol进行编解码。对于read、write
操作,客户端通常会随机选择一个mongos,这在一定程度上提供了简单的负载均衡;不过对于有Cursor的read操作,在Cursor遍历期间,请求只会发送给一个mongos,因为只有那个mongos持有Curosr信息。
(3)config:配置节点,存储集群的metadata数据,数据包含shards节点列表等,metadata的数据量非常小,不会对config server或mongos带来存储上的压力;configserver的负载非常小,他对硬件配置要求很低,只需要较小的内存和存储空即可。线上必须三个config server。
它为集群的枢纽部分mongos使用这些信息将请求路由到shards上,一个集群必须有3个config server。
config在功能系统上修改数据库可能会导致数据极不稳定或不一致。如必须修改config数据库,请使用mongodump创建数据库的完整备份config。
mongo db3.2+版本调整了config server的部署模式,放弃了必须使用三个config server的要求;config server可以采用replica set架构模式,且必须使用wiredtiger存储引擎。这种调整可以有效地提升config server的数据一致性,可以利用replica set的架构优点,
config server的个数可以扩展到50个节点。不过replica set中,不能有“arbiters”、“delayed”类型的members,且它们的“buildIndexes”必须设定为true。

1、启动数据节点
数据节点:192.168.17.132(master)、192.168.17.131(slaver)、192.168.17.130(arbiter)
vi shard.conf
port=10000
pidfilepath=/opt/mongodb/shard.pid
dbpath=/opt/mongodb/db/
directoryperdb=true
logpath=/opt/mongodb/logs/shard.log
logappend=true
fork=true
noprealloc=false
replSet=shard_a
oplogSize=100
shardsvr=true
profile=1
slowms=5
[root@localhost bin]# mongod -f shard.conf
在任意数据节点上mongos --port 10000登陆配置复制集
>use admin
>cfg={_id:'shard_a',members:[{_id:0,host:'192.168.17.132:10000',priority:2},{_id:1,host:'192.168.17.131:10000',priority:1},{_id:2,host:'192.168.17.130:10000',arbiterOnly:true}]};
>rs.initiate(cfg);
>rs.status();
2、启动配置节点
配置节点:192.168.17.134(master)、192.168.17.135(slaver)、192.168.17.136(slaver)
[root@localhost bin]# cat config.conf
port=20000
pidfilepath=/opt/mongodb/config.pid
dbpath=/opt/mongodb/db/
directoryperdb=true
logpath=/opt/mongodb/logs/config.log
logappend=true
fork=true
profile=0
configsvr=true
replSet=shard_b
[root@localhost bin]# mongod -f config.conf
about to fork child process, waiting until server is ready for connections.
forked process: 2288
child process started successfully, parent exiting
在任意配置节点上mongod --port 20000 登陆配置复制集
>use admin
>cfg={_id:'shard_b',members:[{_id:0,host:'192.168.17.136:20000',priority:2},{_id:1,host:'192.168.17.134:20000',priority:1},{_id:2,host:'192.168.17.135:20000',arbiterOnly:true}]};
>rs.initiate(cfg);
>rs.status();
3、启动路由节点
路由节点:192.168.17.133
[root@localhost bin]# cat mongos.conf
configdb=shard_b/192.168.17.136:20000,192.168.17.135:20000,192.168.17.134:20000
port=30000
logpath=/opt/mongodb/logs/mongos.log
fork=true
[root@localhost bin]# mongos -f mongos.conf
about to fork child process, waiting until server is ready for connections.
forked process: 2591
child process started successfully, parent exiting
启动时报错:BadValue: configdb supports only replica set connection string,是因为配置文件要配置复制集
一个数据节点对应一个配置节点,仲裁节点则不需要对应的配置节点。注意在启动路由节点时,要将配置节点ip地址写入到启动命令里。
4、配置sharding
mongo --port 30000 #这里必须连接路由节点
mondos>use admin;
mongos> db.runCommand({addshard:"shard_a/192.168.17.132:10000,192.168.17.131:10000"}); #添加数据节点
mongos> sh.status() #查看状态
5、开启分片功能
对数据库启用分片sh.enableSharding("库名")、sh.shardCollection("库名.表名",{"key":1})
sh.enableSharding("test") 对数据库启用分片
sh.status() 查看分片信息
6、增加安全认证机制keyfile
openssl rand -base64 745 > /opt/mongodb/mongdb.key #生成key
chmod 600 /opt/mongodb/mongodb.key #修改文件权限为600
(1)将该key值放到集群每个节点上,保持一致权限设置为600
(2)修改每个个节点(除mongos节点)配置文件的keyfile参数,并加入auth=true开启验证
(3)重启进入(按照路由节点->配置节点->分片节点的顺序关闭,然后按逆序开启)
pkill mongod
mongod -f shard.conf
mongod -f config.conf
mongos -f mongos.conf
7、创建集群用户
先创建管理员账户
db.createUser({user:"admin",pwd:"123123",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})
对管理员进行身份验证
use admin
db.auth("admin","123123")
(三)master-slave模式
主从模式是实现数据备份的同时,将读写分离,降低数据库的压力。主从模式下,master节点出现故障的时候,需要手动恢复。
master:提供读些功能;slave:提供数据备份和读功能
./mongod --master --dbpath /data/masterdb/ #主节点
./mongod --slave --source <masterip:masterport> --dbpath /data/slavedb/ #备节点
四、补充
(1)硬件配置
1、磁盘
大多数 MongoDB 部署应该使用 RAID-10
2、cpu:mongo DB的性能不会绑定到cpu上,因为mongo DB很少会遇到利用大量内核的工作负载;,所以选择有更快时钟速度的服务器,选用双核高速cpu。mongos路由服务器对cpu资源消耗比较多
3、网卡:最低千M网卡
4、内存:越大越好(64GB)
5、系统采用64位支持更多内存和让支持更大的存储数据,建议文件系统用ext4/xfs
(2)mongoDB的日志
当mongodb运行一段时间后,log文件会变得很大,操作一个日志文件是相当痛苦的,为了避免大日子文件的产生,可以在低峰时段运行每天运行一次db.adminCommand({"logRotate":1}),
使其自动切换日志文件。每天生成一个日志文件。
1、系统日志:记录mongodb启动和停止的操作,以及服务器在运行过程中发生的任何异常信息。启动系统日志,只需要在配置文件里指定logpath参数即可
2、journal日志:数据的更新就先写入journal日志,定期提交(每100ms提交一次),然后再真实数据上执行这些变更。开启journal,会在数据路径下生成journal目录存放journal日志。当崩溃回复时,系统会自动运行joutnal下的日志文件,将数据写入数据库中,不需要运行repair命令。在64系统中是默认开启的,开启是加journal参数,关闭是nojournal参数;限制journal的大小的参数是smallfiles(默认是128M);限制提交间隔的参数是journalCommitlnterval(默认100ms),范围为2到300毫秒;用户可通过写入是指定writeConcern为{j:true}来每次写入时都确保journal刷新
3、oplog主从日志:replica sets模式时,产生的日志;oplogSize是限制日志的大小(单位是MB,默认1024MB),默认可以达到磁盘空间的5%,复制状态和复制延迟可以通过replSetGetStatus命令重新恢复。
master机器
use local
db.oplog.rs.find()
ts: 某个操作的时间戳
op: 操作类型,如下:
i: insert
d: delete
u: update
ns: 命名空间,也就是操作的 collection name
o: document 的内容
查看 master 的 oplog 元数据信息
db.printReplicationInfo()
configured oplog size: 配置的 oplog 文件大小

log length start to end: oplog 日志的启用时间段

oplog first event time: 第一个事务日志的产生时间

oplog last event time: 最后一个事务日志的产生时间

now: 现在的时间
查看 slave 的同步状态:
source: 从库的 IP 及端口
syncedTo: 目前的同步情况,延迟了多久等信息
4、慢查询日志:记录了执行时间超过设定的时间阈值(slowns参数默认100ms)的操作语句;启动参数是profile(0:不开启,1:记录慢命令,2:记录所有命令)。mongo 的慢查询日志是记录是直接存放在系统db里的,记录为自己是system.profile。(db.system.profile.find();)
慢查询日志信息内容参数详解:
ts-该命令在何时执行。
millis Time-该命令执行耗时,以毫秒记.
info-本命令的详细信息.
query-表明这是一个query查询操作.
ntoreturn-本次查询客户端要求返回的记录数.比如, findOne()命令执行时 ntoreturn 为 1.有limit(n) 条件时ntoreturn为n.
query-具体的查询条件(如x>3).
nscanned-本次查询扫描的记录数.
reslen-返回结果集的大小.
nreturned-本次查询实际返回的结果集.
update-表明这是一个update更新操作..
upsert-表明update的upsert参数为true.此参数的功能是如果update的记录不存在,则用update的条件insert一条记录.
moved-表明本次update是否移动了硬盘上的数据,如果新记录比原记录短,通常不会移动当前记录,如果新记录比原记录长,那么可能会移动记录到其它位置,这时候会导致相关索引的更新.磁盘操作更多,加上索引更新,会使得这样的操作比较慢.
insert-这是一个insert插入操作.
getmore-这是一个getmore 操作,getmore通常发生在结果集比较大的查询时,第一个query返回了部分结果,后续的结果是通过getmore来获取的。
(3)mongo DB的监控
mongo DB自带mongostat 和mongotop这两个命令来监控mongo DB的运行情况。
1、mongotop用来跟踪mongo DB的实例,提供每个集合的统计数据。默认情况下,mongotop每一秒刷新一次
输出字段说明:

ns:数据库命名空间,后者结合了数据库名称和集合。

db:数据库的名称。名为 . 的数据库针对全局锁定,而非特定数据库。

total:mongod在这个命令空间上花费的总时间。

read:在这个命令空间上mongod执行读操作花费的时间。

write:在这个命名空间上mongod进行写操作花费的时间。
2、mongostat:它每秒刷新一次状态值,通过这些参数可以观察到一个整体的性能情况
字段说明:
insert: 每秒插入量
query: 每秒查询量
update: 每秒更新量
delete: 每秒删除量
locked: 锁定量
qr | qw: 客户端查询排队长度(读|写)
ar | aw: 活跃客户端量(读|写)
conn: 连接数
time: 当前时间
(4)MongoDB副本集默认会创建local、admin数据库,local数据库主要存储副本集的元数据,admin数据库则主要存储MongoDB的用户、角色等信息。不要往local数据库和admin数据库存储数据。local数据库只会在本地存储数据。
(5)mongoDB停止正在执行的查询
在本地打开家目录下的.mongorc.js拷贝下面的killMyRunningOps函数进去,重新打开mongoshell即可加载这个函数(mongoshell启动时会预读这个文件)。
cat ~/.mongorc.js
killMyRunningOps = function (clientIp) {
var currOp = db.currentOp();
for (op in currOp.inprog) {
if (clientIp == currOp.inprog[op].client.split(":")[0]) {
db.killOp(currentOp.inprog[op].opid)
}
}
}
然后在mongoshell 运行killMyRunningOps(ip)调用这个函数停止正在进行的查询。

(6)MongoDB Sharded cluster 的自动负载均衡目前是由mongos 的后台线程来做的,并且每个集合同一时刻只能有一个迁移任务,负载均衡主要根据集合在各个shard 上chunk 的数量来决定的,相差超过一定阈值(跟chunk 总数量相关)就会触发chunk迁移。
负载均衡默认是开启的,为了避免chunk迁移影响到线上业务,可以通过设置迁移执行窗口,比如只允许凌晨2:00-6:00期间进行迁移。
use config
db.settings.update(
{ _id: "balancer" },
{ $set: { activeWindow : { start : "02:00", stop : "06:00" } } },
{ upsert: true }
)
另外,在进行sharding备份时(通过mongos或者单独备份config server和所有shard),需要停止负载均衡,以免备份出来的数据出现状态不一致问题。
sh.stopBalancer()
五、问题
1、启动过程中出现的问题:
(1)报错:
child process failed,exited with error 1
解决方法:
应该是配置文件中配置的路径错误,修改配置文件的路径
(2)报错:
child process failed,exited with error 48
解决方法:
把进程杀掉和日志文件删掉
(3)报错:
child process failed,exited with error 100
解决方法:
一般是因为锁了,在存放数据的目录下删掉mongod.lock文件和storage.bson文件
2、MongoDB在删除大量数据时,不释放磁盘空间
(1)若是primary节点,先强制将之变为secondary节点,否则跳过此步骤:rs.stepdown();
(2)然后在primary上删除secondary节点:rs.remove("IP:port");

(3)删除secondary节点dbpath下的所有文件

(4)将节点重新加入集群,然后使之自动进行数据的同步:rs.add("IP:port");

(5)等数据同步完成后,循环1-4的步骤可以将集群中所有节点的磁盘空间释放

3、mongoDB启动linux内存大页告警关闭
报错如下:
WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
解决方法:
vi /etc/rc.d/rc.local
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
4、mongodb日志轮询的问题
echo > log会往文件头部插入\n即16进制的0a
在数据库正常运行中,对log文件是加了锁的,强制执行echo > log是无法进行覆盖的,会将所有的数据全部置为0,强制覆盖后,文件头部变成了无数的空白。
mongoDB日志轮询方法调整为kill -SIGUSER1[mongodpid]
5、如果均衡器总是迁移数据影响到集群的整体性能,减小数据块的大小来限制迁移的大小
修改参数chunksize,默认是64MB
6、移除分片命令至少执行两次才能成功删除,执行到state为completed才真正删除,否则就是没用删除成功,该分片处于{"draining" : true}状态,该状态下不但该分片没用删除成功,而且还影响接下来删除其他分片操作,遇到该状态再执行一次removeshard即可,最好就是删除分片时一直重复执行删除命令,直到state为completed; 还有一个需要注意的地方就是:被成功删除的分片如果想要再加入集群时,必须将data数据目录清理干净才可以再加入集群,否则即使能加入成功也不会存储数据,集合都不会被创建 另外:在删除分片的时有可能整个过程出现无限{"draining" : true}状态,等多久还是这样,而且分片上面的块一个都没有移动到别的分片,解决办法是:在config的config数据库的shard集合中找到该分片的信息,并将draining字段由True改为False,再继续试着删除操作” 上面这句会立即返回,实际在后台执行。 在数据移除的过程当中,一定要注意实例的日志信息,可能出现数据块在迁移的过程中,始终找不到边界条件,导致一直数据迁移不成功,一直重试,解决方案是删除边界数据,重启实例;。如果此分片为主分片,需要先迁移主分片。db.runCommand( { movePrimary: "XXX", to: "other" });在完成删除后,所有mongos上运行下面命令,再对外提供服务,当然也可以重新启动所有mongos
7、现在mongo DB使用WiredTiger作为默认存储引擎,WiredTiger内部缓存默认使用较大的一个:50%(RAB-1GB)、256MB。如果一台机器存在多个实例,在内存不足时,操作系统会杀死部分进程。(所以需要调整WiredTiger内存大小,调节cache不需要重启服务,可以动态调整:db.adminCommand( { "setParameter": 1, "wiredTigerEngineRuntimeConfig": "cache_size=xxG"}))
8、mongoDB要备份的话可以添加一个延迟节点,此节点必须是一个priority=0的隐藏节点。最大的作用就是用来容人为的灾,可通过该节点进行回滚。
prioriry=0
hidden=true 设置隐藏节点
slaveDelay =3600 参数设置延迟时间(一小时)
六、mongo DB数据迁移
迁移主节点,需要复制集选举出来一个新的节点,在进行选举的时候,复制集将读写,通常这只会持续很短的时间,不过尽可能在影响较小的时间段内迁移。
1、将主节点降级(rs.stepDown();)
2、关闭当前节点,mongod ---showdown -f mongodb.conf
3、将数据目录(dbpath )转移到新机器上
4、在新机器上启动mongod,其中数据目录为copy的文件目录
5、连接到复制集当前的主节点上,使用rs.reconfig()更新复制集配置文档,然后使用rs.add(ip:port),把新节点添加到复制集,使用rs.status()查看状态。
七、mtools是一组用来解析和过滤mongo DB日志文件的脚本。
yum -y install python-devel 安装python
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py 下载get-pip.py安装包
python get-pip.py 安装pip
pip install mtools[all] 安装mtools
八、基本优化
1、如果慢查询日志的nscanned(扫描的记录数)远大于nreturned(返回结果的记录数)的话,那么就要通过加索引来优化记录定位。创建索引的建议:如果很少读,那么尽量不要添加索引;索引越多,写操作会越慢。
2、使用快速写(开启journal日志)
3、增加安全认证机制keyfile
4、限制mongodb攻击面,避免注入攻击(javascriptEnabled:false)
5、使用limit和sort一起用,可以保证结果的顺序按页浏览
6、在mongo DB中,要避免使undefined(undegined在bson中会转换成null)
7、在mongoDB中,嵌入对象中键的顺序很重要(bson在做搜索是给顺序赋予了意义)
8、不使用多条更新(可以设置multi参数设置为true)
9、指定bind_ip的话如果可能,请使用逻辑DNS主机名而不是IP地址,尤其是在配置副本集成员或分片集群成员时。逻辑DNS主机名的使用避免了由于IP地址更改而导致的配置更改。
10、对于mongoDB,设置比较短的保持周期会带来更好的体验,近似300秒(5分钟)
cat /proc/sys/net/ipv4/tcp_keepalive_time 查看活动保持设置
net.ipv4.tcp_keepalive_time=300添加到/etc/sysctl.conf
11、定期运行db.repairDatabase()来整理记录
12、新部署的查询语句一定要执行explain验证。

mongo DB读写注意事项

1、一定要合理的创建索引
2、大表查询时,只返回你需要的列
3、尽量一次返回所有需要的数据,避免get_move,避免游标操作
4、尽量避免在model里面使用array(数组)类型的字段
5、不要再和数据库直接相关的model里面使用继承
6、事务:mongo db不支持事务
7、主从备份
8、不合理使用embed document(嵌套文件)
把embed关联更改为普通外键关联。当关联对象的数据不固定或者经常发生变化时,一定要避免使用嵌套关联。
9、mongoDB数据库级锁:MongoDB 锁有一种临时放弃机制,当出现需要等待慢速IO 读写数据时,可以先临时放弃,等IO 完成之后再重新获取锁。如果有一些集合操作实在难以避免,可以考虑把这个集合放到一个单独的MongoDB 库里,因为MongoDB 不同库锁是相互隔离的,分离集合可以避免某一个集合操作引发全局阻塞问题。
10、建索引导致整个库阻塞。
解决:
查询运行时间超过200ms操作
db.currentOp({"active" : true,"secs_running" : { "$gt" : 2000 }}) ;
杀死执行时间过长操作操作
db.killOp(opid)
然后通过在创建索引时加 background:true 的选项,让创建工作在后台执行db.values.createIndex({open: 1, close: 1}, {background: true})

posted @ 2019-03-25 22:03  aspen-  阅读(483)  评论(0)    收藏  举报