DBA数据库学习

DBA数据库笔记之(九)MongoDB基础及运维

2024-01-21  本文已影响0人  Mr培

MongoDB安装及常用命令

  1. 面向文档
  2. 高性能
  3. 高可用
  4. 丰富的查询语句
  5. 支持多种主流的开发语言
  1. 游戏
  2. 物流
  3. 社交
  4. 视频直播
  5. 物联网
  6. 电商

database 数据库
collection 集合
document 文档
field 字段
index 索引
primary key 主键

MongoDB6.0的安装

cd /usr/src/
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-6.0.12.tgz
tar zxvf mongodb-linux-x86_64-ubuntu2204-6.0.12.tgz
mv mongodb-linux-x86_64-ubuntu2204-6.0.12 /usr/local/mongodb6/
vim /etc/profile
# 增加
export PATH=$PATH:/usr/local/mongodb6/bin

# 使修改生效
source /etc/profile

mongod --version
# 创建数据和日志文件夹
mkdir -p /data/mongodb/{db,log}
# --fork 后台demo的形式运行
mongod --dbpath /data/mongodb/db --logpath /data/mongodb/log/mongod.log --fork
ps -ef|grep mongodb

连接MongoDB

# centos 系统
wget https://downloads.mongodb.com/compass/mongodb-mongosh-2.1.1.x86_64.rpm
yum install mongodb-mongosh-2.1.1.x86_64.rpm
mongosh --version
mongosh
show dbs
# 设置用户和密码
use admin
db.createUser(
    {
        user:"root",
        pwd:"xxxxx",
        roles:[{role:"root",db:"admin"}]
    }
)
# 重启MongoDB开启验证模式
ps -ef|grep mongodb
kill -9 2536
# 启动
mongod --dbpath /data/mongodb/db --logpath /data/mongodb/log/mongod.log --fork --auth
# 登录
mongosh -u root -p xxxxx
show dbs

db相关命令

# 创建和使用一个库都可以用 use
use martin
db.test.insert({"num":1})
show dbs
use martin
db.dropDatabase()

用户相关命令

use admin
db.createUser(
    {
        user:"root",
        pwd:"xxxxx",
        roles:[{role:"root",db:"admin"}]
    }
)
use martin
db.createUser(
    {
        user:"martin_u",
        pwd:"xxxxx",
        roles:[{role:"readWrite",db:"martin"}]
    }
)
# 只能查看当前库的用户
show users;

use admin
show users;

# 或者
db.system.users.find()

常用内置角色

  1. root 超级权限
  2. readWrite 某个非系统库的读写权限
  3. read 某个非系统库的读权限
  4. readWriteAnyDatabase 对所有库的读写权限
  5. readAnyDatabase 对所有库的读权限

集合管理命令

use martin
db.createCollection("one")
show tables;
# 或者
show collections;
# db.集合名字.drop()
db.one.drop()

CRUD操作

# 如果没有这个集合就会自动创建
db.one.insertOne({name:"li"})

# 或者
db.one.insert({name:"zhang"})
# 插入多字段
db.one.inset({name:"wang",age:23})
# 插入多行
db.one.insetMany([{name:"zeng",age:23},{name:"wang",age:24}])
# 循环插入多行
for (var 1=1;i <= 101; i++) db.two.insert({num:i,name:'a'});
# 查询one集合所有数据
db.one.find()
# 查询two集合所有数据
db.two.find()

# 带条件查询
db.one.find({name:'zhang'})
db.one.update({name:'zhang'},{$set:{name:'li'}})
# 修改多行
db.one.updateMany({name:'li'},{$set:{name:'liu'}})
# 只删除一条
db.one.deleteOne({name:'liu'})
# 删除满足条件的所有数据
db.one.deleteMany({name:'liu'})
# 删除某个集合中的全部数据
db.one.deleteMany({})

条件相关命令

$gt 大于; $lt 小于
$gte 大于等于;$lte 小于等于

db.one.find({age:{$gt:20}})
db.one.find({age:{$lt:20}})
db.one.find({$and:[{"name":"li"},{"age":28}]})
db.one.find({$or:[{"name":"zhang"},{"age":16}]})

统计计算

# 升序
db.one.find().sort({"age":1})
db.one.find({age:{$gt:20}}).sort({"age":1})
# 降序
db.one.find().sort({"age":-1})
# 请求
db.one.countDocuments()
db.one.countDocuments({age"{$gt:20}})
# 求某个字段和
db.three.aggregate([{'$group':{_id:'$class','sum_score':{'$sum':'$score'}}}])
# 请平均值
db.three.aggregate([{'$group':{_id:'$class','avg_score':{'$avg':'$score'}}}])
# 最大值
db.three.aggregate([{'$group':{_id:'$class','max_score':{'$max':'$score'}}}])
# 最低分
db.three.aggregate([{'$group':{_id:'$class','min_score':{'$min':'$score'}}}])

MongoDB查询优化

慢查询

# 查看慢查询是否开启;was:0 表示没有开启;slowms:100 慢查询预值单位毫秒;sampleRate:1采样率,1都采样
db.getProfilingStatus()
# 开启慢查询 1 表示开启,100超过100毫秒的语句记录到慢查询
db.setProfilingLevel(1,100)
# 关闭慢查询
db.setProfilingLevel(0)
# 测试表
for (var i=1 ; i <= 100000 ; i++) db.slow_test.insert({num:i,name:"a"})
# 开启慢查询
db.setProfilingLevel(1,100)
# 执行语句
db.slow_test.find({"num":9999})
# 查询慢查询记录
db.system.profile.find()

command 执行的命令
keysExamined:0 索引扫描的行数,0表示这条语句没有走索引
docsExamined:100000 表示扫描的文档数
nreturned:1 表示返回的文档数
responseLenngth:151 表示命令返回的字节数
millis:117 表示命令执行的时间,117毫秒
planSummary:'COLLSCAN' 表示扫描的方式,COLLSCAN表示全集合扫描
ts 表示命令执行的时间点
client:'127.0.0.1' 表示慢查询的客户端

查询计划

# 默认queryPlanner查询优化器选择查询优化的详细信息
db.slow_test.find({num:99}).explain()
db.slow_test.find({num:99}).explain("queryPlanner")
# executionStats 详细分布查询计划和分布时间
db.slow_test.find({num:99}).explain("executionStats")
# allPlansExecution 表示查看所有的执行计划 或者 true
db.slow_test.find({num:99}).explain("allPlansExecution")
db.slow_test.find({num:99}).explain(true)
db.slow_test.find({num:99}).explain(true)
# 分析结果

nReturnd:1 返回的行数
executionTimeMillis:86 花费的时间
totalKeysExamined:0 扫描了多少索引项
totalDocsExamined:100000 扫描了多少文档
stage:'COLLSCAN' 全集合扫码,IXSCAN索引扫码

# 添加索引 为slow_test表num字段添加一个增序索引
db.slow_test.createIndex({"num":1})
# 再查询执行计划
db.slow_test.find({num:99}).explain(true)

索引管理

# 写入测试数据
for (var i=1 ; i <= 10000 ; i++) db.index_test.insert({num:i,name:'a'})
# 查询集合的前10个文档
db.index_test.find().limit(10)
# 添加所以 1 按升序创建索引,-1 按降序创建索引
db.idnex_test.createIndex({"num":1})
db.index_test.getIndexes()
# 接索引名字
db.idnex_test.dropIndex("num_1")

多种索引类型

db.index_test.createIndex({"num":1,"name":1})
# 测试数据
db.index_test_01.insert({name:"martin",tag:["a","b","c"]})
# 创建索引
db.index_test.createIndex({"tag":1})
# 查看执行计划
db.index_test_01.find({tag:"b"}).explain(true)
# 一个集合最多创建一个全文索引
db.index_test_01.createIndex({"name":"text"})
# 哈希索引不支持范围查询且不支持多键hash
db.index_test_01.createIndex({"name":"hashed "})
# 写入地理位置数据
db.index_test_02.insertMamy([{loc:[9,9]},{loc:[11,11]},{loc:[100,100]}])
# 创建地理位置索引
db.index_test_02.createIndex({"loc":"2d"})
# 查询地理数据
db.index_test_02.find({loc:{$geoWithin:{$box:[[10,10],[12,12]]}}})

索引原理

MongoDB索引原理.jpg

MongoDB副本集(高可用方案)

副本集架构介绍

MongoDB副本集架构.jpg

副本集原理

创建副本集之后会进行一次全量同步,在primary节点克隆出除local库之外的数据库

# 查看local库
mongosh -u root -p xxx
show dbs

并且会扫描出原数据库中每个集合并将所有数据插入到这些集合自己的副本中,在复制过程中目标成员会拉取新添加的oplog记录,这样就可以记录在全量数据传输过程中,在primary所做的增量操作。全量数据导入完后再应用oplog可以保证跟源端数据一致,当数据同步之后如果有primary节点有修改操作,就会记录到oplog里面,在secondary有一个线程会持续监听log的变化,有变化的时候会把变动传到secondary节点再进行回放,保证持续数据是同步的。

如果没有指定oplog大小,如果是内存的存储引擎默认是物理内存的5%,最小值是50M,最大值是50G;如果是WiredTiger存储引擎默认是物理内存的5%,最小值是999M,最大值是50G。

在副本集当中节点之间两两是互相发送心跳的,当超过一定时间没有收到对方心跳时判断对方失联,如果失联的是主节点那从节点就会发起选举,选出新的主节点,如果失联的是从节点则不会触发新的选举直接踢出失联的从节点。

副本集的安装

三台机器

cd /usr/src/
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-6.0.12.tgz
tar zxvf mongodb-linux-x86_64-ubuntu2204-6.0.12.tgz
mv mongodb-linux-x86_64-ubuntu2204-6.0.12 /usr/local/mongodb6/

# 修改环境变量
vim /etc/profile
# 增加
export PATH=$PATH:/usr/local/mongodb6/bin

# 使修改生效
source /etc/profile

mongod --version
# 创建数据和日志文件夹
mkdir -p /data/mongodb27001/{data,conf,run,logs}
# 随机生成一个复杂的密码;rand 随机;-base64 随机数据以base编码输出;756字节数
openssl rand -base64 756 > /ddata/mongodb27001/conf/keyfile
chmod 400 /ddata/mongodb27001/conf/keyfile
# 传输到其它两台机器
scp /ddata/mongodb27001/conf/keyfile 192.168.12.162:/data/mongodb27001/conf/
scp /ddata/mongodb27001/conf/keyfile 192.168.12.163:/data/mongodb27001/conf/
vim /data/mongodb27001/conf/mongod.conf

# 系统日志
systemLog:
    # 文件类型
    destination: file
    # true 追加的方式
    logAppend: true
    # 路径
    path: /data/mongodb27001/logs/mongod.log
# 存储相关的配置
storage:
    dbPath: /data/mongodb27001/data
    # 日志配置
    journal:
        enabled: true
# 进程管理相关的配置
processManagement:
    fork: true
    pidFilePath: /data/mongodb27001/run/mongod.pid
    timeZoneInfo: /usr/share/zoneinfo
# 网络相关的配置
net:
    port: 27001
    # 0.0.0.0 对所有机器开放访问
    bindIp: 0.0.0.0
# 集群相关配置
replication:
    oplogSizeMB: 4096
    # 副本集的名字,同一个副本集每一个成员replSetName要一样
    replSetName: martin_repl
# 加密相关
security:
    keyFile: /data/mongodb27001/conf/keyfile
# 三台机器
mongod -f /data/mongodb27001/conf/mongod.conf
# 三台机器安装mongosh
# centos 系统
wget https://downloads.mongodb.com/compass/mongodb-mongosh-2.1.1.x86_64.rpm
yum install mongodb-mongosh-2.1.1.x86_64.rpm
mongosh --version
# 第一台机器
mongosh --port 27001
rs.initiate({
    _id:"martin_repl",
    members:[
        {_id: 0,host:'192.168.12.161:27001',priority:1},
        {_id: 1,host:'192.168.12.162:27001',priority:1},
        {_id: 2,host:'192.168.12.163:27001',arbiterOnly:true}
    ]
})

_id 集群名字

# 查看集群状态
rs.status()

创建用户

# passwordPrompt()表示过会输入密码
admin=db.getSiblingDB("admin")
admin.createUser({
    user:"root",
    pwd:passwordPrompt(),
    roles:[{role:"userAdminAnyDatabase",db:"admin"}]
})
# 需要密码
show dbs
# 登录
mongosh --port 27001 -u root -p
show dbs
db.getSiblingDB("admin").createUser({
    user:"repl",
    pwd:passwordPrompt(),
    roles:[{"role":"clusterAdmin","db":"admin"}]
})
mongosh --port 27001 -u root -p
db.getSiblingDB("martin").createUser({
    user:"martin_rw",
    pwd:passwordPrompt(),
    roles:[{"role":"readWrite","db":"martin"}]
})

集群测试

# 在primary主节点
mongosh --port 27001 -u martin_rw -p xxxx martin
# 写入操作
db.one.insertOne({name:'liu'})

# 查看从节点
mongosh --port 27001 -u martin_rw -p xxxx martin
# 从节点默认不能查询
db.one.find()
# 设置从节点可以查询数据
db.getMongo().setReadPref('secondaryPreferred')
# 再查询
db.one.find()

帮忙写一个Go程序,操作MongoDB副本集,副本集的连接信息如下:
mongodb://martin_rw:xxx@192168.12.161:27001,192.168.12162:27001/martin?replicaSet=martin_rep
集群的名字是martin_repl
在martin这个库里面,每秒往集合write_test里写一行文档,每一行文档需要不一样

# 调整修改代码
# 运行代码
# 查看MongoDB数据
# 继续写入数据
# kill掉mongodb主节点
# 查看正在运行的代码
# 在从查看信息
mongosh --port 27001 -u martin_rw -p xxxx martin
rs.status()
# 在启动关闭的节点
mongod -f /data/mongodb27001/conf/mongod.conf

副本集常见管理操作

# replSetDown 表示一旦这个主节点成功退出那么这个节点收到命令到120秒内不能再次成为主节点
# 在主节点执行
db.adminCommand({replSetDown:120})
rs.status()
mkdir -p /data/mongodb27002/{data,conf,run,logs}
# 修改配置文件
vim /data/mongodb27002/conf/mongod.conf

# 系统日志
systemLog:
    # 文件类型
    destination: file
    # true 追加的方式
    logAppend: true
    # 路径
    path: /data/mongodb27002/logs/mongod.log
# 存储相关的配置
storage:
    dbPath: /data/mongodb27002/data
    # 日志配置
    journal:
        enabled: true
# 进程管理相关的配置
processManagement:
    fork: true
    pidFilePath: /data/mongodb27002/run/mongod.pid
    timeZoneInfo: /usr/share/zoneinfo
# 网络相关的配置
net:
    port: 27002
    # 0.0.0.0 对所有机器开放访问
    bindIp: 0.0.0.0
# 集群相关配置
replication:
    oplogSizeMB: 4096
    # 副本集的名字,同一个副本集每一个成员replSetName要一样
    replSetName: martin_repl
# 加密相关
security:
    keyFile: /data/mongodb27002/conf/keyfile
    
    
# 复制密钥文件
cp /data/mongodb27001/conf/keyfile /data/mongodb27002/conf/
# 启动27002
mongod -f /data/mongodb27002/conf/mongod.conf


# 添加新的成员;使用集群管理账号
mongosh --port 27001 -u repl -p xxxx
rs.status()
# 添加新的节点
rs.add({host:"192.168.12.161:27001"})
rs.status()
rs.remove("192.168.12.161:27002")
rs.status()

一主两副本架构介绍

MongoDB一主两副本架构介绍.jpg

MongoDB分片集群

副本集满足不了需求就可以使用分片集群

  1. 数据量过大
  2. 数据持续增长
  3. 副本集已经满足不了高并发写入的性能要求了

一般情况下副本集够用的情况还是强烈建议使用副本集,分片集群的主键跟多,维护更复杂

  1. 对应用透明
  2. 数据会自动平衡
  3. 动态扩容

分片集群的架构

MongoDB分片集群的架构.jpg

部署Config Servers

# 需要安装三个Config Servers
mkdir -p /data/mongodbconfig27020/{data,conf,run,logs}
vim /data/mongodbconfig27020/conf/mongod.conf

sharding:
    clusterRole: configsvr
systemLog:
    destination: file
    logAppend: true
    path: /data/mongodbconfig27020/logs/mongod.log
storage:
    dbPath: /data/mongodbconfig27020/data
    journal:
        enabled: true
processManagement:
    fork: true
    pidFilePath: /data/mongodbconfig27020/run/mongod.pid
    timeZoneInfo: /usr/share/zoneinfo
net:
    port: 27020
    bindIp: 0.0.0.0
replication:
    oplogSizeMB: 4096
    replSetName: config_repl

clusterRole 集群名字
replSetName 要配置 config_ 关键字开头

# 三台机器都要启动
mongod -f /data/mongodbconfig27020/conf/mongod.conf
# 随便选一台Config Servers的机器登录
mongosh --port 27020

# 副本集创建
rs.initiate({
    _id:"config_repl",
    configsvr:true,
    members:[
        {_id: 0,host:'192.168.12.161:27020'},
        {_id: 1,host:'192.168.12.162:27020'},
        {_id: 2,host:'192.168.12.163:27020'}
    ]
})
rs.status()

启动MongoDB分片实例

分片实例用来存放数据的

# 三台机器都需要
mkdir -p /data/mongodbshard27021/{data,conf,run,logs}
mkdir -p /data/mongodbshard27022/{data,conf,run,logs}
vim /data/mongodbshard27021/conf/mongod.conf

sharding:
    clusterRole: shardsvr
systemLog:
    destination: file
    logAppend: true
    path: /data/mongodbconfig27021/logs/mongod.log
storage:
    dbPath: /data/mongodbconfig27021/data
    journal:
        enabled: true
processManagement:
    fork: true
    pidFilePath: /data/mongodbconfig27021/run/mongod.pid
    timeZoneInfo: /usr/share/zoneinfo
net:
    port: 27021
    bindIp: 0.0.0.0
replication:
    oplogSizeMB: 4096
    replSetName: shardsvr_repl_27021
    
# 第二份
vim /data/mongodbshard27022/conf/mongod.conf

sharding:
    clusterRole: shardsvr
systemLog:
    destination: file
    logAppend: true
    path: /data/mongodbconfig27022/logs/mongod.log
storage:
    dbPath: /data/mongodbconfig27022/data
    journal:
        enabled: true
processManagement:
    fork: true
    pidFilePath: /data/mongodbconfig27022/run/mongod.pid
    timeZoneInfo: /usr/share/zoneinfo
net:
    port: 27022
    bindIp: 0.0.0.0
replication:
    oplogSizeMB: 4096
    replSetName: shardsvr_repl_27022
mongod -f /data/mongodbshard27021/conf/mongod.conf
mongod -f /data/mongodbshard27022/conf/mongod.conf
# 启动后每台机器应该有三个实例
ps -ef | grep mogo
# 在一台机器登录
mongosh --port 27021
# 创建集群
rs.initiate({
    _id:"shardsvr_repl_27021",
    members:[
        {_id: 0,host:'192.168.12.161:27021'},
        {_id: 1,host:'192.168.12.162:27021'},
        {_id: 2,host:'192.168.12.163:27021'}
    ]
})
rs.status()
# 再换一个端口
mongosh --port 27022
# 添加集群
rs.initiate({
    _id:"shardsvr_repl_27022",
    members:[
        {_id: 0,host:'192.168.12.161:27022'},
        {_id: 1,host:'192.168.12.162:27022'},
        {_id: 2,host:'192.168.12.163:27022'}
    ]
})
rs.status()

配置和启动mongos

# 三台机器随便选一台
mkdir /data/mongos27017/{logs,conf,run} -p

vim /data/mongos27017/conf/mongos.conf

sharding:
    configDB:config_repl/192.168.12.161:27020,192.168.12.162:27020,192.168.12.163:27020
systemLog:
    destination: file
    logAppend: true
    path: /data/mongos27017/logs/mongos.log
processManagement:
    fork: true
    pidFilePath: /data/mongos27017/run/mongod.pid
net:
    port: 27017
    bindIp: 0.0.0.o

configDB : config_repl config Servers实例的名字,192.168.12.161:27020,192.168.12.162:27020,192.168.12.163:27020三台Config Servers的ip和端口

mongos --config /data/mongos27017/conf/mongos.conf
mongosh --port 27017
# 创建管理员用户
admin = db.getSiblingDB("admin")
admin.createUser(
    {
        user:"root",
        pwd: passwordPrompt(),
        roles:[{role:"userAdminAnyDatabase",db:"admin"}]
    }
)
# 重新登录
mongosh --port 27017 -u root -p
# 创建业务用户
db.getSiblingDB("admin").createUser(
    {
        user:"martin_rw",
        pwd: passwordPrompt(),
        roles:[{"role":"readWrite","db":"martin"}]
    }
)

分片配置

# shardsvr_repl_27021 分片集群的名字,后面是分片集群的ip和端口
sh.addShard("shardsvr_repl_27021/192.168.12.161:27021,192.168.12.162:27021,192.168.12.163:27021")
sh.addShard("shardsvr_repl_27022/192.168.12.161:27022,192.168.12.162:27022,192.168.12.163:27022")
# 用业务用户账号登录
mogosh martin --port 27017 -u martin_wr -p
# 为martin这个库启动分片
sh.enableSharding("martin")
# 再对collection就行分片;martin.userinfo 库名+集合的名字;_id 分片的键/分片的字段;如果 martin.userinfo被drop掉就要重新配置分片规则
sh.shardCollection("martin.userinfo",{_id:"hsahed"})

# 查看分片详情
sh.status()
# 循环往martin分片写入数据
for (var i=1; i <= 20; i++) db.userinfo.insertOne({userid:i,username:'a'});
db.userinfo.find()

# 只看第一个分片的数据
mongosh martin --port 27021
db.userinfo.find()
# 查看第二个分片的数据
mongosh martin --port 27022
db.userinfo.find()

分片集群高可用测试

编写一个Go程序,连接MongoDB的mongos,
每秒往里面写入一行文档,
有用户密码,直接连接到业务库martin
每次写入成功或者失败,
都有带时间戳的日志信息

# 运行代码后

show tables;
sb.shard_write_test.find()
sb.shard_write_test.countDocuments()
# 分片集群 kill掉主节点
mongosh --port 27021
# 查看主节点
rs.status()

ps -ef|grep mongo
kill -9 25920

# 程序正常运行

MongoDB性能压测

环境准备

cd /usr/src/
wget https://github.com/brianfrankcooper/YCSB/releases/download/0.17.0/ycsb-mongodb-binding-0.17.0.tar.gz
tar zxvf ycsb-mongodb-binding-0.17.0.tar.gz

运行只读压测

cd ycsb-mongodb-binding-0.17.0
# 连接primary节点
mongosh --port 27001 -u root -p
# 创建压测用户
db.getSiblingDB("ycsb").createUser({
    user:"ycsb_rw",
    pwd:passwordPrompt(),
    roles:[{"role":"readWrite","db":"ycsb"}]
})
# 修改配置文件
vim workloads/workloada
# 新增配置
mongodb.url=mongodb://ycsb_rw:密码@192.168.12.161:2001/?authSource=ycsb

# 原有配置
# 表示要加载到数据库里面的记录数
recordcount=1000
# 表示要执行的操作数
operationcount=1000
# 工作负载
workload=size.ycsb.workloads.CoreWorkload

# 读的操作比例
readproportion=1
# update的操作比例;目前要压测只读需要修改为0
updateproportion=0
# 加载数据
./bin/ycsb load mongodb -P workloads/workloada
# 压测
./bin/ycsb run mongodb -P workloads/workloada

运行读写压测

vim workloads/workloada
# 修改
readproportion=0.5
updateproportion=0.5
# 删除已经加载的压测数据
mongosh --port 27001 -u ycsb -p
show tables;
db.usertable.drop()
# 加载压测数据
./bin/ycsb load mongodb -P workloads/workloada
# 压测
./bin/ycsb run mongodb -P workloads/workloada

MongoDB响应慢排查

准备

mongodb4.4开始MongoDB工具和MongoDB server是分开发布的,需要单独部署mongo工具

mongo工具下载

cd /usr/src
# 以centos7.0为例
wget https://fastdl.mongodb.org/tools/db/mongodb-database-tools-rhel70-x86_64-100.9.4.rpm
yum install mongodb-database-tools-rhel70-x86_64-100.9.4.rpm -y
mongosh --port 27001 -u root -p
use admin
db.grantRolesToUser("root",["clusterMonitor"])

通过工具分析MongoDB的性能

mongostat --uri="mongodb://root:密码@192.168.12.161:27001/?replicaSet=martin_repl&authSource=admin"

insert query update delete getmore command 最近一秒操作的次数
dirty :WiredTiger 脏数据,未刷盘的数据占总内存的比例
used :WiredTiger 内存使用率
flushes :WiredTiger 最近一秒刷到磁盘的次数
vsize 使用了多少虚拟内存
res 实际使用的内存大小
qrw 读写等待的队列长度
arw 执行读写操作的活跃客户端是否是短时间活跃连接数突增
net_in net_out 表示进出对的流量
conn 连接数

set 副本集的名字
repl 副本集的状态
time 当前时间

mongotop --uri="mongodb://root:密码@192.168.12.161:27001/?replicaSet=martin_repl&authSource=admin"

MongoDB的备份和恢复

准备

# 三台机器
ps -ef | grep 27001
mongod -f /data/mongodb27001/conf/mongod.conf 

# 登录到集群查看信息
mongosh martin --port 27001 -u martin -p
rs.status()
db.baktest.insetOne({name:'liu'})
# 另一台机器安装
cd /usr/src/
wget https://fastdl.mongodb.org/tools/db/mongodb-database-tools-rhel70-x86_64-100.9.4.rpm
yum install mongodb-database-tools-rhel70-x86_64-100.9.4.rpm -y

mongodump/mongorestore备份恢复

# 在secondary节点备份;创建备份文件夹
mkdir -p /data/mongodb/backup
cp /data/mongodb/backup
# 执行备份命令
mongodump -u martin_rw -p xxxx --host localhost:27001 --db martin --out ./mongobak

# 恢复
show tables;
# 清空集合
db.baktest.drop()
db.one.drop()
db.write_test.drop()
# 在primary节点恢复;创建恢复文件夹
mkdir /data/mongodb/backup
# secondary节点。将备份文件传输到primary节点
cd mongobak/
scp -r martin/ 192.168.12.161:/data/mongodb/backup
# 在primary节点
cd /data/mongodb/backup
# -d martin 表示要恢复到的db里
mongorestore --host 192.168.12.161:27001 -u martin_rw -p xxx -d martin /data/mongodb/backup/martin/
mongosh martin --port 27001 -u martin_rw -p
show tables;
cd /data/mongodb/backup/
# 连接集群的方式备份;只写primary和secondary节点的ip和端口;--readPreference=secondary 只会到secondary节点去备份,如果secondary都宕机就会报错,secondaryPreferred 如果所有secondary都宕机就回去primary节点备份
mongodump --host="martin_repl/192.168.12.161:27001,192.168.12.162:27001" --readPreference=secondaryPreferred -u martin_rw -p xxxx --db martin --out ./repl_mongobak

# 恢复和单实例一样
mongodump --host="192.168.12.161:27017" --readPreference=secondaryPreferred -u martin_rw -p xxxx --db martin --out ./shard_mongobak
# 恢复一样

mongoexport/mongoimport备份恢复

# -d martin 备份的库;-c baktest 备份的集合;-o 输出文件
mongoexport --host localhost:27001 -u martin_rw -p xxxx -d martin -c baktest -o baktest.json

# 恢复;在primary节点,删除baktest集合,将备份文件baktest.json传输到当前节点机器
mongoimport --host localhost:27001 -u martin_rw -p xxxx -d martin -c baktest --file baktest.json
# 备份
mongoexport --host="martin_repl/192.168.12.161:27001,192.168.12.162:27001" --readPreference=secondaryPreferred -u martin_rw -p xxxx -d martin -c baktest -o repl_baktest.json
# 恢复一样
mongoexport --host="192.168.12.161:27017" --readPreference=secondaryPreferred -u martin_rw -p xxxx -d martin -c baktest -o shard_baktest.json

# 恢复一样

编写自动化备份脚本

编写一个MongoDB副本集的备份脚本
备份文件夹是 /data/mongobackup
备份命令为: mongodump --host="martin_repl/192.168.12.161:27001,192.168.12.162:27001" --readPreference=secondary -u martin_rw -p xxxx --db martin --out ./repl_mongobak
备份的子文件夹以bak_开头
每次删除15天之前的备份

vim mongo_repl_backup.sh
chmod +x mongo_repl_backup.sh

MongoDB的数据安全

保证MongoDB数据安全的策略

  1. 身份认证
  2. 配置不同的用户
  3. 设置复杂的密码
  4. 权限控制
  5. 网络隔离
  6. 定期备份

MongoDB监控

MongoDB常见监控项

# 登录副本集primary节点
mongosh --port 27001 -u root -p
# 如果执行不了就需要增加权限
db.serverStatus().connections
# 增加权限
use admin
db.grantRolesToUser("root",["clusterMonitor])

current: 18 当前连接数
available: 801 未使用但是可以用的连接数
totalCreated: 244 启动到现在总共创建的连接数
active: 5 活跃连接数
threaded: 18 客户端连接的线程数

db.serverStatus().mem

bits:64 表示MongoDB运行实例的架构
resident:28 使用的屋里内存大小单位M
virtual:2964 使用虚拟内存大小
supported:true MongoDB进程所依赖的底层操作系统是否支持扩展的内存信息

db.serverStatus().wiredTiger.cache
db.serverStatus().locks
db.serverStatus().opcounters
use martin
db.stats();
# 只能在admin执行
use admin
db.runCommand(
    {
        top:1
    }
)
rs.status();
上一篇 下一篇

猜你喜欢

热点阅读