Mogodb概述
MongoDB 将数据存储为一个文档。MongoDB是一个基于分布式文件存储的数据库。
FirstName="Arun", Address="St. Xavier's Road", Spouse=[{Name:"Kiran"}], Children=[{Name:"Rihit", Age:8}].
FirstName="Sameer",Address="8 Gandhi Road".
注意:以上数据有两个不同的文档(以"."分隔)。以这种方式存储数据即为文件存储的数据库。 MongoDB是一个面向文档的数据库。
mongo特点
1.快,分布式,高可用,大数据量
高性能: Mongodb 提供高性能的数据持久性,尤其是支持嵌入式数据模型减少数据库系统上的
I/O 操作,索引支持能快的查询,并且可以包括来嵌入式文档和数组中的键
丰富的语言查询: Mongodb支持丰富的查询语言来支持读写操作(CRUD)以及数据汇总,文本
搜索和地理空间索引
高可用性: Mongodb的复制工具,成为副本集,提供自动故障转移和数据冗余,
水平可扩展性: Mongodb提供了可扩展性,作为其核心功能的一部分,分片是将数据分,在一组
计算机上。
支持多种存储引擎: WiredTiger存储引擎和、MMAPv1存储引擎和InMemory 存储引擎
2.和mysql对比
mysql mongo
库 库
表 集合
字段 文档
mysql存储一条数据:
id name age
1 xxx 28
mongo存储一条数据:
{
id: 1,
name: xxx,
age: 28
}
{
id: 1,
name: xxx,
age: 28,
vip: baoji
}
{"FirstName":"ke","LastName":"me","email":"hikeme@aa"}
#(易企秀)
mongodb应用场景
https://www.zhihu.com/question/32071167
游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
视频直播,使用 MongoDB 存储用户信息、礼物信息等
电商场景,使用 MongoDB
商城上衣和裤子两种商品,除了有共同属性,如产地、价格、材质、颜色等外,还有各自有不同的属性集,如上衣的独有属性是肩宽、胸围、袖长等,裤子的独有属性是臀围、脚口和裤长等
安装部署
1.安装命令
yum install libcurl openssl -y
mkdir /opt/mongo_cluster/ -p
mkdir /data/soft -p
cd /data/soft/
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.13.tgz
tar zxvf mongodb-linux-x86_64-3.6.13.tgz -C /opt/mongo_cluster/
cd /opt/mongo_cluster/
ln -s mongodb-linux-x86_64-3.6.13 mongodb
cp /opt/mongo_cluster/mongodb/bin/* /usr/local/bin/
mkdir /opt/mongo_cluster/mongo_27017/{conf,logs,pid} -p
mkdir /data/mongo_cluster/mongo_27017 -p
2.配置文件
cat > /opt/mongo_cluster/mongo_27017/conf/monogdb.conf <<EOF
systemLog:
destination: file
logAppend: true
path: /opt/mongo_cluster/mongo_27017/logs/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/mongo_cluster/mongo_27017
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/mongo_cluster/mongo_27017/pid/mongod.pid
net:
port: 27017
bindIp: 127.0.0.1,10.0.0.51
EOF
3.启动
mongod -f /opt/mongo_cluster/mongo_27017/conf/monogdb.conf
4.检查
ps -ef|grep mongod
netstat -lntup|grep mongod
5.登录测试
mongo db01:27017
6.关闭
2种关闭方式:
1.mongod -f /opt/mongo_cluster/mongo_27017/conf/monogdb.conf --shutdown
2.登录后操作,注意,必须使用本地IP登录
mongo localhost:27017
use admin
db.shutdownServer()
解决告警
默认启动后有很多警告:
问题1:
** WARNING: Access control is not enabled for the database.
Read and write access to data and configuration is unrestricted.
问题解决: 配置文件里添加相关参数
security:
authorization: enabled
问题2:
** WARNING: You are running this process as the root user, which is not recommended.
解决方法:1
useradd mongo
chown -R mongo:mongo
chown -R mongo:mongo /opt/mongo_cluster/
chown -R mongo:mongo /data/mongo_cluster/
su - mongo
mongod -f /opt/mongo_cluster/mongo_27017/conf/monogdb.conf
解决方法:2
解决方法2:创建systemcd启动文件
cat >/lib/systemd/system/mongod.service<<EOF
[Unit]
Description=MongoDB Database Server
Documentation=https://docs.mongodb.org/manual
After=network.target
[Service]
User=mongod
Group=mongod
Environment="OPTIONS=-f /opt/mongo_27017/conf/mongodb.conf"
ExecStart=/opt/mongodb/bin/mongod \$OPTIONS
ExecStartPre=/usr/bin/chown -R mongod:mongod /opt/mongo_27017
ExecStartPre=/usr/bin/chown -R mongod:mongod /data/mongo_27017
PermissionsStartOnly=true
PIDFile=/opt/mongo_27017/pid/mongod.pid
Type=forking
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for for mongod as specified in
# http://docs.mongodb.org/manual/reference/ulimit/#recommended-settings
[Install]
WantedBy=multi-user.target
EOF
useradd mongod -M -s /sbin/nologin
systemctl daemon-reload
systemctl start mongod
问题3:
** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
We suggest setting it to 'never'
** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
We suggest setting it to 'never'
问题解决:
方法一:
https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/
方法:
echo "never" > /sys/kernel/mm/transparent_hugepage/enabled
echo "never" > /sys/kernel/mm/transparent_hugepage/defrag
检查:
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag
报错小结:
1.配置文件里IP写错了
2.配置文件缩进不对
3.数据目录或配置目录权限不对
4.压缩包上传不完整,导致解压文件缺失
5.在root模式下启动的进程,然后切换到普通用户就启动不了了,因为权限不对
6.内存不足可能也起不来
基础查看命令
1.查看
db #查看当前库在哪
show databases/show dbs
show tables/show collections
use admin #切换库
db/select database()
2.帮助命令
Help: 显示帮助。
db.help() 显示数据库方法的帮助。
db.<collection>.help() 显示收集方法的帮助, <collection>可以是现有的集合或不存在的集合的名称。
show dbs 打印服务器上所有数据库的列表。
use <db> 将当前数据库切换到<db>。该 mongoshell 变量 db 被设置为当前数据库。
show collections 打印当前数据库的所有集合的列表
show users 打印当前数据库的用户列表。
show roles 打印用于当前数据库的用户定义和内置的所有角色的列表。
show profile 打印需要 1 毫秒或更多的五个最近的操作。有关详细信息,请参阅数据库分析器上的文档。
show databases 打印所有可用数据库的列表。
load() 执行一个 JavaScript 文件。
基本操作命令
插入命令:
1.插入单行数据
db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.test.insert({"name":"yazhang","age":28,"ad":"北京市朝阳区"})
db.test.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区"})
db.test.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区","sex":"boy"})
2.插入多行数据
db.inventory.insertMany( [
{ "item": "journal", "qty": 25, "size": { "h": 14, "w": 21, "uom": "cm" }, "status": "A" },
{ "item": "notebook", "qty": 50, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "A" },
{ "item": "paper", "qty": 100, "size": { "h": 8.5, "w": 11, "uom": "in" }, "status": "D" },
{ "item": "planner", "qty": 75, "size": { "h": 22.85, "w": 30, "uom": "cm" }, "status": "D" },
{ "item": "postcard", "qty": 45, "size": { "h": 10, "w": 15.25, "uom": "cm" }, "status": "A" }
]);
查询命令:
1.查询所有数据
db.test.find()
2.查询单条数据
db.inventory.findOne()
3.按照条件查询
db.inventory.find( { status: "D" } )
db.inventory.find( {"size.uom": "in"} )
db.inventory.find( { status: "A", qty: { $lt: 30 } } )
db.inventory.find(
{
status: "A",
qty: { $gt: 20 },
"size.w" : { $gt: 10 }
}
)
db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
db.inventory.find(
{
$or: [
{ status: "A" },
{ qty: { $lt: 30 } }
]
}
)
db.inventory.find( {status: "A",$or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]} )
db.inventory.find(
{
status: "A",
$or:
[
{ qty: { $lt: 30 } },
{ item: /^p/ }
]
}
)
单条更新命令:
db.inventory.updateOne(
{ "item" : "paper" },
{
$set: { "size.uom" : "cm", "status" : "P" },
$currentDate: { "lastModified": true }
}
)
多条更新命令:
db.inventory.updateMany(
{ "qty" : { $lt: 50 } },
{
$set: { "size.uom" : "cm", "status": "P" },
$currentDate : { "lastModified": true }
}
)
索引
普通的查询
db.test.find({"age":{ $lt: 30 }})
查看执行计划
db.test.find({"age":{ $lt: 30 }}).explain()
创建索引
db.test.createIndex({ age: 1 })
查看索引
db.test.getIndexes()
再次查看执行计划
db.test.find({"age":{ $lt: 30 }}).explain()
出现IXSCAN表示走索引了
删除数据
查看数据
db.inventory.find( { "status": "D" } )
删除复合条件的一条数据
db.inventory.deleteOne({ "status": "D" })
删除复合条件的多条数据
db.inventory.deleteMany({ "status": "P" })
第八章: mongo常用工具
mongotop
mongostat
insert:每秒插入数(带*的表示复制集的从库,下同)
query:每秒查询数
update:每秒更新数
delete:每秒删除数
getmore:每秒返回的游标数
command:每秒的命令数(其中从库用管道符|将本地数据和复制数据隔开) 。
dirty: wiredtiger特有的参数,记录wiredtiger缓存中脏数据的比例。
used: wiredtiger特有的参数,记录wiredtiger缓存使用百分比。
flusher: 每个查询间隔之间的checkpoint触发次数。
Vsize:虚拟内存使用量。
res:物理内存使用量。
qrw: 客户端等待从MongoDB实例读写数据的队列长度,|隔开。
arw:执行读写操作的活跃客户端数量,|隔开。
netIn:MongoDB实例的网络进流量。
netOut:MongoDB实例的网络出流量。
conn: 连接数。
set:复制集名称。
repl:复制集中的状态。
用户认证
mongo默认存在的库
test:登录时默认存在的库
管理MongoDB有关的系统库
admin库:系统预留库,MongoDB系统管理库
local库:本地预留库,存储关键日志
config库:MongoDB配置信息库
验证库: 建立用户时use到的库,在使用用户时,要加上验证库才能登陆。
对于管理员用户,必须在admin下创建.
1. 建用户时,use到的库,就是此用户的验证库
2. 登录时,必须明确指定验证库才能登录
3. 通常,管理员用的验证库是admin,普通用户的验证库一般是所管理的库设置为验证库
4. 如果直接登录到数据库,不进行use,默认的验证库是test,不是我们生产建议的.
5. 从3.6 版本开始,不添加bindIp参数,默认不让远程登录,只能本地管理员登录。
1.创建管理用户
use admin
db.createUser(
{
user: "admin",
pwd: "123456",
roles:[
{
role: "root",
db:"admin"
}
]
}
)
db.getUsers()
2.修改配置文件
security:
authorization: enabled
3.登录测试
mongo db01:27017 -u admin -p --authenticationDatabase admin
show dbs
4.创建普通用户
use test
db.createUser(
{
user: "myTester",
pwd: "xyz123",
roles: [
{ role: "readWrite", db: "test" },
{ role: "read", db: "test2" }
]
}
)
5.测试访问
5.1.先使用admin用户去创建test2的数据:
mongo db01:27017 -u admin -p 123456 --authenticationDatabase admin
use test2
db.test2.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.test2.find()
5.2.使用test用户去验证
切换到test库,发现可以写入和查看
mongo db01:27017 -u myTester -p xyz123 --authenticationDatabase test
use test
db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.test.find()
切换到test2库,发现只能查看,但是不能写入
use test2
db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.test.find()
mongo副本集
1.创建目录
mkdir -p /opt/mongo_cluster/mongo_2801{7,8,9}/{conf,logs,pid}
2.创建配置文件
cat>/opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf<<EOF
systemLog:
destination: file
logAppend: true
path: /opt/mongo_cluster/mongo_28017/logs/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/mongo_cluster/mongo_28017
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/mongo_cluster/mongo_28017/pid/mongod.pid
net:
port: 28017
bindIp: 127.0.0.1,10.0.0.51
replication:
oplogSizeMB: 1024
replSetName: linux4
EOF
3.复制修改其他实例的配置文件
cd /opt/mongo_cluster/
cp mongo_28017/conf/mongo_28017.conf mongo_28018/conf/mongo_28018.conf
cp mongo_28017/conf/mongo_28017.conf mongo_28019/conf/mongo_28019.conf
sed -i 's#28017#28018#g' mongo_28018/conf/mongo_28018.conf
sed -i 's#28017#28019#g' mongo_28019/conf/mongo_28019.conf
4.创建数据目录
mkdir /data/mongo_cluster/mongo_2801{7,8,9}
5.启动多实例
mongod -f /opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf
mongod -f /opt/mongo_cluster/mongo_28018/conf/mongo_28018.conf
mongod -f /opt/mongo_cluster/mongo_28019/conf/mongo_28019.conf
6.初始化集群配置
config = {
_id : "linux4",
members : [
{_id : 0, host : " db01:28017"},
{_id : 1, host : " db01:28018"},
{_id : 2, host : " db01:28019"},
]
}
rs.initiate(config)
7.主库插入数据
db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.test.insert({"name":"zhangya","age":27,"ad":"北京市朝阳区"})
db.test.insert({"name":"yazhang","age":28,"ad":"北京市朝阳区"})
db.test.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区"})
db.test.insert({"name":"xiaozhang","age":28,"ad":"北京市朝阳区","sex":"boy"})
8.从库登录验证是否可以读写
注意! 默认shell登录mongo副本集,副本是不可以读取的,提示报错如下:
linux4:SECONDARY> db.test.find()
Error: error: {
"operationTime" : Timestamp(1567674072, 1),
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk",
"$clusterTime" : {
"clusterTime" : Timestamp(1567674072, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
解决方法:
1.登录后执行命令临时生效,退出终端后失效
rs.slaveOk()
2.写入隐藏的配置文件,每次登录都生效
[mongo@db-01 ~]$ cat .mongorc.js
rs.slaveOk()
9.副本集常用命令
rs.status(); //查看整体复制集状态
rs.isMaster(); // 查看当前是否是主节点
rs.conf(); //查看复制集配置信息
模拟故障转移
mongod -f /opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf --shutdown
故障恢复
mongod -f /opt/mongo_cluster/mongo_28017/conf/mongo_28017.conf
副本集权重调整
1.查看当前副本集的配置信息,会发现,默认所有结点的权重都为1
rs.conf()
2.修改当前配置并且热更新
config = rs.conf()
config.members[0].priority=100
rs.reconfig(config)
3.主节点主动降级
rs.stepDown() #只能在主节点执行
4.检查是否切换成功
rs.status()
5.恢复原始的权重
config = rs.conf()
config.members[0].priority=1
rs.reconfig(config)
添加节点
1.先创建新节点的目录
mkdir /opt/mongo_cluster/mongo_28010/{conf,logs,pid} -p
mkdir /data/mongo_cluster/mongo_28010
cd /opt/mongo_cluster/
cp mongo_28017/conf/mongo_28017.conf mongo_28010/conf/mongo_28010.conf
sed -i 's#28017#28010#g' mongo_28010/conf/mongo_28010.conf
mongod -f /opt/mongo_cluster/mongo_28010/conf/mongo_28010.conf
mongo db01:28010
2.集群配置添加新节点
rs.add("db01:28010") #在主节点操作,不能在28010本身操作
剔除节点
rs.remove("db01:28010")
增加仲裁节点
rs.addArb(("db01:28010")
#保持奇数个节点(包括主节点在内),如果是偶数个,再增加个(仲裁节点(Arb),仲裁节点可以放在任一台中,只要能与集群通信就行,因为占有资源少。
备份与恢复
两种备份工具:
1.mongoexport/mongoimport:json csv
异构平台迁移 mysql <---> mongodb
同平台,跨大版本:mongodb 2 ----> mongodb 3
2.mongodump/mongorestore
日常备份恢复时使用.
3.备份命令
mongoexport和mongoimport:
导出成json(默认导出为json格式)
mongoexport --port 28017 -d(库) test -c(表) inventory -o inventory.json
导出成csv
mongoexport --port 28017 -d test -c inventory --type=csv -f _id,item,qty,size,status -o inventory.csv
导入json命令
mongoimport --port 28017 -d test -c inventory inventory.json
导入csv命令
mongoimport --port 28017 -d test -c inventory --type=csv --headerline --file inventory.csv
mongodump和mongorestore
备份:
mkdir backup
mongodump --port 28017 -o backup
mongodump --port 28017 -o backup --gzip
恢复:
mongorestore --port 28017 -d test backup/test/
mongorestore --port 28017 -d test backup/test/ --gzip
模拟误删除恢复
操作场景:
1点:
全备
oldzhang
mongodump --port 28017 --oplog -o backup
6点:
创建了数据库
oldzhang1
use oldzhang1
db.test.insert({"name":"zhangya1"})
7点:
创建了数据库
oldzhang2
use oldzhang2
db.test.insert({"name":"zhangya2"})
10点:
oldzhang1被删除了
use oldzhang1
db.dropDatabase()
11点:
写入了新的数据
use oldzhang3
11点:
停掉了负载均衡,此时没有新数据写入了
模拟恢复:
1.查找误删除的时间点并记录下来
db.oplog.rs.find({ns:"oldzhang1.$cmd"}).pretty();
时间点:
1567684132
2.备份local库
mongodump --port 28017 -d local -c oplog.rs -o backup
3.把local库里的oplog.rs替换到全备的里面
cd backup/local/
cp oplog.rs.bson ../oplog.bson
rm -rf backup/local
4.恢复到删除以前的时间点的数据
mongorestore --port 28017 --oplogReplay --oplogLimit "1567684132:1" --drop backup
5.查看数据是否被恢复
show dbs
7 --oplog -o backup
6点:
创建了数据库
oldzhang1
use oldzhang1
db.test.insert({"name":"zhangya1"})
7点:
创建了数据库
oldzhang2
use oldzhang2
db.test.insert({"name":"zhangya2"})
10点:
oldzhang1被删除了
use oldzhang1
db.dropDatabase()
11点:
写入了新的数据
use oldzhang3
11点:
停掉了负载均衡,此时没有新数据写入了
模拟恢复:
1.查找误删除的时间点并记录下来
db.oplog.rs.find({ns:"oldzhang1.$cmd"}).pretty();
时间点:
1567684132
2.备份local库
mongodump --port 28017 -d local -c oplog.rs -o backup
3.把local库里的oplog.rs替换到全备的里面
cd backup/local/
cp oplog.rs.bson ../oplog.bson
rm -rf backup/local
4.恢复到删除以前的时间点的数据
mongorestore --port 28017 --oplogReplay --oplogLimit "1567684132:1" --drop backup
5.查看数据是否被恢复
show dbs