MongoDB-核心技术
1、什么时候使用Mongodb?
我的数据量是有亿万级或者需要不断扩容
需要2000-3000以上的读写每秒
新应用、需求会变、数据模型无法确定
我需要整合多个外部数据源
我的系统需要99.999%高可用
我的系统需要大量的地理位置查询
我的系统需要提供最小的latency
我要管理的主要数据对象 < 10
2、Mongodb特点
MongoDB与关系型数据库的最大区别:没有固定的行列组织数据结构
高性能:
Mongodb提供高性能的数据持久性
尤其是支持嵌入式数据模型减少数据库系统上的I/O操作
索引支持能快的查询,并且可以包括来嵌入式文档和数组中的键
丰富的语言查询:
Mongodb支持丰富的查询语言来支持读写操作(CRUD)以及数据汇总,文本搜索和地理空间索引
高可用性:
Mongodb的复制工具,成为副本集,提供自动故障转移和数据冗余
水平可扩展性:
Mongodb提供了可扩展性,作为其核心功能的一部分,分片是将数据分,在一组计算机上
支持多种存储引擎:
WiredTiger存储引擎和、MMAPv1存储引擎和InMemory存储引擎
3、mongodb应用场景
游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
视频直播,使用 MongoDB 存储用户信息、礼物信息等,用户评论
电商场景,使用 MongoDB
商城上衣和裤子两种商品,除了有共同属性,如产地、价格、材质、颜色等外,还有各自有不同的属性集,如上衣的独有属性是肩宽、胸围、袖长等,裤子的独有属性是臀围、脚口和裤长等
4、逻辑结构
Mongodb 逻辑结构 MySQL逻辑结构
库database 库
集合(collection) 表
文档(document) 数据行
选择之所以称之为选择,肯定是痛苦的!
------->oldguo
5、系统准备
(1)redhat或centos6.2以上系统
(2)系统开发包完整
(3)ip地址和hosts文件解析正常
(4)iptables防火墙&SElinux关闭
(5)关闭大页内存机制
# 如何关闭大页内存机制?
linux系统root用户下
在vi /etc/rc.local最后添加如下代码
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
[root@kvm ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@kvm ~]# echo never > /sys/kernel/mm/transparent_hugepage/defrag
# 其他系统关闭参照官方文档:
https://docs.mongodb.com/manual/tutorial/transparent-huge-pages/
---------------
为什么要关闭?
Transparent Huge Pages (THP) is a Linux memory management system
that reduces the overhead of Translation Lookaside Buffer (TLB)
lookups on machines with large amounts of memory by using larger memory pages.
However, database workloads often perform poorly with THP,
because they tend to have sparse rather than contiguous memory access patterns.
You should disable THP on Linux machines to ensure best performance with MongoDB.
6、MongoDB安装
# 创建所需用户和组
useradd mongod
passwd mongod
# 创建mongodb所需目录结构
mkdir -p /mongodb/conf
mkdir -p /mongodb/log
mkdir -p /mongodb/data
# 上传并解压软件到指定位置
[root@db01 data]# cd /data
[root@db01 data]# tar xf mongodb-linux-x86_64-rhel70-3.6.12.tgz
[root@db01 data]# cp -r /data/mongodb-linux-x86_64-rhel70-3.6.12/bin/* /mongodb/bin
# 设置目录结构权限
chown -R mongod:mongod /mongodb
# 设置用户环境变量
su - mongod
vi .bash_profile
export PATH=/mongodb/bin:$PATH
source .bash_profile
# 启动mongodb
su - mongod
mongod --dbpath=/mongodb/data --logpath=/mongodb/log/mongodb.log --port=27017 --logappend --fork
# 登录mongodb
[mongod@server2 ~]$ mongo
7、使用配置文件
YAML模式
NOTE:
YAML does not support tab characters for indentation: use spaces instead.
--系统日志有关
systemLog:
destination: file
path: "/mongodb/log/mongodb.log" --日志位置
logAppend: true --日志以追加模式记录
--数据存储有关
storage:
journal:
enabled: true
dbPath: "/mongodb/data" --数据路径的位置
-- 进程控制
processManagement:
fork: true --后台守护进程
pidFilePath: <string> --pid文件的位置,一般不用配置,可以去掉这行,自动生成到data中
--网络配置有关
net:
bindIp: <ip> -- 监听地址
port: <port> -- 端口号,默认不配置端口号,是27017
-- 安全验证有关配置
security:
authorization: enabled --是否打开用户名密码验证
------------------以下是复制集与分片集群有关----------------------
replication:
oplogSizeMB: <NUM>
replSetName: "<REPSETNAME>"
secondaryIndexPrefetch: "all"
sharding:
clusterRole: <string>
archiveMovedChunks: <boolean>
---for mongos only
replication:
localPingThresholdMs: <int>
sharding:
configDB: <string>
---
++++++++++++++++++++++
YAML例子
cat > /mongodb/conf/mongo.conf <<EOF
systemLog:
destination: file
path: "/mongodb/log/mongodb.log"
logAppend: true
storage:
journal:
enabled: true
dbPath: "/mongodb/data/"
processManagement:
fork: true
net:
port: 27017
bindIp: 10.0.0.51,127.0.0.1
EOF
mongod -f /mongodb/conf/mongo.conf --shutdown //关闭mongodb
mongod -f /mongodb/conf/mongo.conf //启动
8、使用systemctld管理mongodb
# 在root用户下
exit/su - root
# systemctld脚本
[root@db01 ~]# cat > /etc/systemd/system/mongod.service <<EOF
[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target
[Service]
User=mongod
Type=forking
ExecStart=/mongodb/bin/mongod --config /mongodb/conf/mongo.conf //如果是多实例的话针对不同的配置文件启动关闭
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/mongodb/bin/mongod --config /mongodb/conf/mongo.conf --shutdown //如果是多实例的话针对不同的配置文件启动关闭
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
[root@db01 ~]# systemctl restart mongod
[root@db01 ~]# systemctl stop mongod
[root@db01 ~]# systemctl start mongod
9、mongodb常用操作
9.1 mongodb默认存在的库
test:登录时默认存在的库
管理MongoDB有关的系统库
admin库:系统预留库,MongoDB系统管理库
local库:本地预留库,存储关键日志
config库:MongoDB配置信息库
show databases/show dbs
show tables/show collections
use admin
db/select database()
9.2 命令种类
# db 对象相关命令
db //查看当前库
db.[TAB][TAB]
db.help()
db.oldboy.help()
db.status() //查看集合和大小
# rs 复制集有关(replication set):
rs.[TAB][TAB]
rs.help()
# sh 分片集群(sharding cluster)
sh.[TAB][TAB]
sh.help()
9.2 mongodb对象操作
mongo mysql
库 -----> 库
集合 -----> 表
文档 -----> 数据行
# 库的操作
> use test
>db.dropDatabase()
{ "dropped" : "test", "ok" : 1 }
# 集合的操作
app> db.createCollection('a')
{ "ok" : 1 }
app> db.createCollection('b')
方法2:当插入一个文档的时候,一个集合就会自动创建。
use oldboy
db.test.insert({name:"zhangsan"})
db.stu.insert({id:101,name:"zhangsan",age:20,gender:"m"})
show tables;
db.stu.insert({id:102,name:"lisi"})
db.stu.insert({a:"b",c:"d"})
db.stu.insert({a:1,c:2})
db.log.drop() //删除log集合
db.log.renameCollection("log1") //集合改名,log改为log1
# 文档操作
数据录入:
for(i=0;i<10000;i++){db.log.insert({"uid":i,"name":"mongodb","age":6,"date":new
Date()})}
查询数据行数:
> db.log.count()
全表查询;默认显示20行,输入it显示下一行
> db.log.find()
> db.log.findone() //查询第一行
每页显示50条记录:
> DBQuery.shellBatchSize=50;
按照条件查询
> db.log.find({uid:999})
以标准的json格式显示数据
> db.log.find({uid:999}).pretty()
{
"_id" : ObjectId("5cc516e60d13144c89dead33"),
"uid" : 999,
"name" : "mongodb",
"age" : 6,
"date" : ISODate("2019-04-28T02:58:46.109Z")
}
删除集合中所有记录
app> db.log.remove({})
查询去掉当前集合中某列的重复数据
db.log.distinct("name")
集合中索引+数据压缩存储之后的大小,字节单位
db.log.totalSize()
10、用户及权限管理
- 验证库: 建立用户时use到的库,在用户远程登录时,要加上验证库才能登陆。
对于管理员用户,必须在admin下创建.
- 建用户时,use到的库,就是此用户的验证库
- 用户远程登录时,必须明确指定验证库才能登录
- 通常,管理员用户的验证库是admin,普通用户的验证库一般是所管理的库设置为验证库
- 如果直接登录到数据库,不进行use,默认的验证库是test,不是我们生产建议的.
- 从3.6 版本开始,不添加bindIp参数,默认不让远程登录,只能本地管理员登录。
10.1 用户创建语法
# 基本语法说明:
use admin //进入要赋权的库
db.createUser
{
user: "<name>", //用户名
pwd: "<cleartext password>", //密码
roles: [ //权限/角色
{ role: "<role>", //权限类型,通常role类型:root(超级管理员), readWrite,read
db: "<database>" } , //有权限的库,如果一个用户管理多个库,加个逗号接着写有权限的库
{ role: "<role>",db: "<database>" }
...
]
}
# 用户管理例子
创建超级管理员:管理所有数据库(必须use admin再去创建)
use admin //进入要赋权的库
db.createUser(
{
user: "root",
pwd: "root123",
roles: [ { role: "root", db: "admin" } ] //admin是管理库,给admin库授权相当于是给全局授权
}
)
mongo -uroot -proot123 admin
# 创建应用用户
use oldboy //进入要赋权的库
db.createUser(
{
user: "app01",
pwd: "app01",
roles: [ { role: "readWrite" , db: "oldboy" } ]
}
)
mongo -uapp01 -papp01 app
# 验证用户
db.auth('root','root123')
# 配置文件中,加入以下配置
security:
authorization: enabled
# 重启mongodb
mongod -f /mongodb/conf/mongo.conf --shutdown
mongod -f /mongodb/conf/mongo.conf
# 登录验证
mongo -uroot -proot123 admin
mongo -uroot -proot123 10.0.0.53/admin
或者
mongo
use admin
db.auth('root','root123')
# 查询mongodb中的用户信息
mongo -uroot -proot123 10.0.0.53/admin
db.system.users.find().pretty()
# 删除用户(root管理员身份登录,use到验证库)
mongo -uroot -proot123 10.0.0.53/admin
use oldboy1
db.dropUser("app02")
# 用户管理注意事项
1. 建用户要有验证库,管理员admin,普通用户是要管理的库
2. 登录时,注意验证库
mongo -uapp01 -papp01 10.0.0.51:27017/oldboy
3. 重点参数
net:
port: 27017
bindIp: 10.0.0.51,127.0.0.1
security:
authorization: enabled
11、MongoDB复制集RS(ReplicationSet)
11.1 基本原理
基本构成是1主2从的结构,自带互相监控投票机制(Raft(MongoDB) Paxos(mysql MGR 用的是变种)分布式协议)
如果发生主库宕机,复制集内部会进行投票选举,选择一个新的主库替代原有主库对外提供服务。同时复制集会自动通知
客户端程序,主库已经发生切换了。应用就会连接到新的主库。
至少三个节点,也可以是一主一从一Arbiter结构,Arbiter节点不复制数据,只负责投票;
复制集RS能保证所有节点数据一致性;基于raft协议,所有节点之间自动进行心跳检测,宕机后进行选举,自动切换,剩余主机自动构建主从关系,节点恢复自动自愈。
在mongodb中,一个节点只能出现在一个复制集中,不能出现级联状态。
11.2 Replication Set配置过程详解
# 规划
三个以上的mongodb节点(或多实例)
# 环境准备
# 多个端口
28017、28018、28019、28020
# 多套目录
su - mongod
mkdir -p /mongodb/28017/conf /mongodb/28017/data /mongodb/28017/log
mkdir -p /mongodb/28018/conf /mongodb/28018/data /mongodb/28018/log
mkdir -p /mongodb/28019/conf /mongodb/28019/data /mongodb/28019/log
mkdir -p /mongodb/28020/conf /mongodb/28020/data /mongodb/28020/log
# 多套配置文件
/mongodb/28017/conf/mongod.conf
/mongodb/28018/conf/mongod.conf
/mongodb/28019/conf/mongod.conf
/mongodb/28020/conf/mongod.conf
# 配置文件内容
cat > /mongodb/28017/conf/mongod.conf <<EOF
systemLog:
destination: file
path: /mongodb/28017/log/mongodb.log
logAppend: true
storage:
journal:
enabled: true
dbPath: /mongodb/28017/data
directoryPerDB: true
#engine: wiredTiger
wiredTiger: //引擎
engineConfig:
cacheSizeGB: 1 //缓冲区大小
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
net:
bindIp: 10.0.0.51,127.0.0.1
port: 28017
replication: //复制集相关的专用配置
oplogSizeMB: 2048 //日志大小,日志存放在表里,默认磁盘空间5%
replSetName: my_repl //复制集名,与配置时复制集名相同
EOF
\cp /mongodb/28017/conf/mongod.conf /mongodb/28018/conf/
\cp /mongodb/28017/conf/mongod.conf /mongodb/28019/conf/
\cp /mongodb/28017/conf/mongod.conf /mongodb/28020/conf/
sed 's#28017#28018#g' /mongodb/28018/conf/mongod.conf -i
sed 's#28017#28019#g' /mongodb/28019/conf/mongod.conf -i
sed 's#28017#28020#g' /mongodb/28020/conf/mongod.conf -i
# 启动多个实例备用
mongod -f /mongodb/28017/conf/mongod.conf
mongod -f /mongodb/28018/conf/mongod.conf
mongod -f /mongodb/28019/conf/mongod.conf
mongod -f /mongodb/28020/conf/mongod.conf
netstat -lnp|grep 280
# 启动多个实例备用
mongod -f /mongodb/28017/conf/mongod.conf
mongod -f /mongodb/28018/conf/mongod.conf
mongod -f /mongodb/28019/conf/mongod.conf
mongod -f /mongodb/28020/conf/mongod.conf
netstat -lnp|grep 280
11.3 配置复制集
# 1主2从,从库普通从库
mongo --port 28017 admin
config = {_id: 'my_repl', members: [
{_id: 0, host: '10.0.0.8:28017'},
{_id: 1, host: '10.0.0.8:28018'},
{_id: 2, host: '10.0.0.8:28019'}]
}
rs.initiate(config) //构建集群,括号里为复制集名
# 1主1从1个arbiter结构
mongo -port 28017 admin
config = {_id: 'my_repl', members: [
{_id: 0, host: '10.0.0.51:28017'},
{_id: 1, host: '10.0.0.51:28018'},
{_id: 2, host: '10.0.0.51:28019',"arbiterOnly":true}]
}
rs.initiate(config)
# 查询复制集状态
rs.status(); //查看整体复制集状态
rs.isMaster(); // 查看当前是否是主节点
rs.conf(); //查看复制集配置信息
11.4 添加删除节点
rs.remove("ip:port"); // 删除一个节点
rs.add("ip:port"); // 新增从节点
rs.addArb("ip:port"); // 新增仲裁节点
例子:
添加 arbiter节点
1、连接到主节点
[mongod@db03 ~]$ mongo --port 28018 admin
2、删除一个节点
3、添加仲裁节点
my_repl:PRIMARY> rs.addArb("10.0.0.53:28020")
4、查看节点状态
my_repl:PRIMARY> rs.isMaster()
{
"hosts" : [
"10.0.0.53:28017",
"10.0.0.53:28018",
"10.0.0.53:28019"
],
"arbiters" : [
"10.0.0.53:28020"
],
rs.remove("ip:port"); // 删除一个节点
例子:
my_repl:PRIMARY> rs.remove("10.0.0.53:28019");
{ "ok" : 1 }
my_repl:PRIMARY> rs.isMaster()
rs.add("ip:port"); // 新增从节点
例子:
my_repl:PRIMARY> rs.add("10.0.0.53:28019")
{ "ok" : 1 }
my_repl:PRIMARY> rs.isMaster()
11.4 特殊从节点
- 介绍
arbiter节点:主要负责选主过程中的投票,但是不存储任何数据,也不提供任何服务
hidden节点:隐藏节点,不参与选主,也不对外提供服务。
delay节点:延时节点,数据落后于主库一段时间,因为数据是延时的,也不应该提供服务或参与选主,所以通常会配合hidden(隐藏)
一般情况下会将delay+hidden一起配置使用
# 配置延时节点(一般延时节点也配置成hidden)
cfg=rs.conf()
cfg.members[2].priority=0 //不进行投票;中括号内为节点索引,从0开始,非_id号码
cfg.members[2].hidden=true //不参与业务
cfg.members[2].slaveDelay=120 //延时从库
rs.reconfig(cfg)
取消以上配置
cfg=rs.conf()
cfg.members[2].priority=1
cfg.members[2].hidden=false
cfg.members[2].slaveDelay=0
rs.reconfig(cfg)
配置成功后,通过以下命令查询配置后的属性
rs.conf();
11.5 副本集其它操作命令
查看副本集的配置信息
admin> rs.conf()
查看副本集各成员的状态
admin> rs.status()
++++++++++++++++++++++++++++++++++++++++++++++++
--副本集角色切换(不要人为随便操作)
admin> rs.stepDown()
注:
admin> rs.freeze(300) //锁定从,使其不会转变成主库
freeze()和stepDown单位都是秒。
+++++++++++++++++++++++++++++++++++++++++++++
设置副本节点可读:在副本节点执行
admin> rs.slaveOk()
eg:
admin> use app
switched to db app
app> db.createCollection('a')
{ "ok" : 0, "errmsg" : "not master", "code" : 10107 }
查看副本节点(监控主从延时)
admin> rs.printSlaveReplicationInfo()
source: 192.168.1.22:27017
syncedTo: Thu May 26 2016 10:28:56 GMT+0800 (CST)
0 secs (0 hrs) behind the primary
OPlog日志(备份恢复章节)
12、MongoDB Sharding Cluster 分片集群
mongodb分布式架构:路由、配置(节点信息、分布策略)、数据存储节点(shard节点)组成
配置节点是复制集结构,只能是一主两从,不能有arbiter节点
路由节点是mongos
shard节点是复制集结构
4个物理节点,配置节点一主两从分配到3台物理节点
12.1 Shard节点配置过程
规划
10个实例:38017-38026
(1)configserver:38018-38020
3台构成的复制集(1主两从,不支持arbiter)38018-38020(复制集名字configsvr)
(2)shard节点:
sh1:38021-23 (1主两从,其中一个节点为arbiter,复制集名字sh1)
sh2:38024-26 (1主两从,其中一个节点为arbiter,复制集名字sh2)
(3) mongos:
38017
目录创建
mkdir -p /mongodb/38021/conf /mongodb/38021/log /mongodb/38021/data
mkdir -p /mongodb/38022/conf /mongodb/38022/log /mongodb/38022/data
mkdir -p /mongodb/38023/conf /mongodb/38023/log /mongodb/38023/data
mkdir -p /mongodb/38024/conf /mongodb/38024/log /mongodb/38024/data
mkdir -p /mongodb/38025/conf /mongodb/38025/log /mongodb/38025/data
mkdir -p /mongodb/38026/conf /mongodb/38026/log /mongodb/38026/data
修改配置文件
第一组复制集搭建:21-23(1主 1从 1Arb)
cat > /mongodb/38021/conf/mongodb.conf <<EOF
systemLog:
destination: file
path: /mongodb/38021/log/mongodb.log
logAppend: true
storage:
journal:
enabled: true
dbPath: /mongodb/38021/data
directoryPerDB: true
#engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
net:
bindIp: 10.0.0.8,127.0.0.1
port: 38021
replication:
oplogSizeMB: 2048
replSetName: sh1 //复制集名可自己取
sharding:
clusterRole: shardsvr //在集群中的角色,固有名字,不能随便取
processManagement:
fork: true
EOF
\cp /mongodb/38021/conf/mongodb.conf /mongodb/38022/conf/
\cp /mongodb/38021/conf/mongodb.conf /mongodb/38023/conf/
sed 's#38021#38022#g' /mongodb/38022/conf/mongodb.conf -i
sed 's#38021#38023#g' /mongodb/38023/conf/mongodb.conf -i
第二组节点:24-26(1主1从1Arb)
cat > /mongodb/38024/conf/mongodb.conf <<EOF
systemLog:
destination: file
path: /mongodb/38024/log/mongodb.log
logAppend: true
storage:
journal:
enabled: true
dbPath: /mongodb/38024/data
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
net:
bindIp: 10.0.0.8,127.0.0.1
port: 38024
replication:
oplogSizeMB: 2048
replSetName: sh2
sharding:
clusterRole: shardsvr
processManagement:
fork: true
EOF
\cp /mongodb/38024/conf/mongodb.conf /mongodb/38025/conf/
\cp /mongodb/38024/conf/mongodb.conf /mongodb/38026/conf/
sed 's#38024#38025#g' /mongodb/38025/conf/mongodb.conf -i
sed 's#38024#38026#g' /mongodb/38026/conf/mongodb.conf -i
启动所有节点,并搭建复制集
mongod -f /mongodb/38021/conf/mongodb.conf
mongod -f /mongodb/38022/conf/mongodb.conf
mongod -f /mongodb/38023/conf/mongodb.conf
mongod -f /mongodb/38024/conf/mongodb.conf
mongod -f /mongodb/38025/conf/mongodb.conf
mongod -f /mongodb/38026/conf/mongodb.conf
ps -ef |grep mongod
mongo --port 38021 admin
config = {_id: 'sh1', members: [
{_id: 0, host: '10.0.0.8:38021'},
{_id: 1, host: '10.0.0.8:38022'},
{_id: 2, host: '10.0.0.8:38023',"arbiterOnly":true}]
}
rs.initiate(config)
mongo --port 38024 admin
config = {_id: 'sh2', members: [
{_id: 0, host: '10.0.0.8:38024'},
{_id: 1, host: '10.0.0.8:38025'},
{_id: 2, host: '10.0.0.8:38026',"arbiterOnly":true}]
}
rs.initiate(config)
12.2 Config节点配置
# 目录创建
mkdir -p /mongodb/38018/conf /mongodb/38018/log /mongodb/38018/data
mkdir -p /mongodb/38019/conf /mongodb/38019/log /mongodb/38019/data
mkdir -p /mongodb/38020/conf /mongodb/38020/log /mongodb/38020/data
# 修改配置文件
cat > /mongodb/38018/conf/mongodb.conf <<EOF
systemLog:
destination: file
path: /mongodb/38018/log/mongodb.conf
logAppend: true
storage:
journal:
enabled: true
dbPath: /mongodb/38018/data
directoryPerDB: true
#engine: wiredTiger
wiredTiger:
engineConfig:
cacheSizeGB: 1
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
net:
bindIp: 10.0.0.8,127.0.0.1
port: 38018
replication:
oplogSizeMB: 2048
replSetName: configReplSet
sharding:
clusterRole: configsvr //固有角色名
processManagement:
fork: true
EOF
\cp /mongodb/38018/conf/mongodb.conf /mongodb/38019/conf/
\cp /mongodb/38018/conf/mongodb.conf /mongodb/38020/conf/
sed 's#38018#38019#g' /mongodb/38019/conf/mongodb.conf -i
sed 's#38018#38020#g' /mongodb/38020/conf/mongodb.conf -i
# 启动节点,并配置复制集
mongod -f /mongodb/38018/conf/mongodb.conf
mongod -f /mongodb/38019/conf/mongodb.conf
mongod -f /mongodb/38020/conf/mongodb.conf
mongo --port 38018 admin
config = {_id: 'configReplSet', members: [
{_id: 0, host: '10.0.0.8:38018'},
{_id: 1, host: '10.0.0.8:38019'},
{_id: 2, host: '10.0.0.8:38020'}]
}
rs.initiate(config)
注:configserver 可以是一个节点,官方建议复制集。configserver不能有arbiter。
新版本中,要求必须是复制集。
注:mongodb 3.4之后,虽然要求config server为replica set,但是不支持arbiter
12.3 mongos最后一个节点配置
# 创建目录
mkdir -p /mongodb/38017/conf /mongodb/38017/log
# 配置文件
cat > /mongodb/38017/conf/mongos.conf <<EOF
systemLog:
destination: file
path: /mongodb/38017/log/mongos.log
logAppend: true
net:
bindIp: 10.0.0.8,127.0.0.1
port: 38017
sharding:
configDB: configReplSet/10.0.0.8:38018,10.0.0.8:38019,10.0.0.8:38020
processManagement:
fork: true
EOF
# 启动mongos
mongos -f /mongodb/38017/conf/mongos.conf
# 分片集群添加节点
连接到其中一个mongos(10.0.0.51),做以下配置
(1)连接到mongs的admin数据库
# su - mongod
mongo 10.0.0.8:38017/admin
(2)添加分片,将shard信息加入集群
db.runCommand( { addshard : "sh1/10.0.0.8:38021,10.0.0.8:38022,10.0.0.8:38023",name:"shard1"} )
db.runCommand( { addshard : "sh2/10.0.0.8:38024,10.0.0.8:38025,10.0.0.8:38026",name:"shard2"} )
(3)列出分片
mongos> db.runCommand( { listshards : 1 } )
(4)整体状态查看
mongos> sh.status();
12.4 使用分片集群
-
将把每一个分片的存储单元定义为chunk,以逻辑单元chunk存储数据;
1.拆分:每个chunk默认64MB,当数据存满64M时,数据会分裂为两个新的chunk单元,每个数据32M,再满再分裂;但是只会在一个复制集里(shard)分裂;
2.迁移:Mongodb插件balance会自动检查节点的chunk的分布情况,如果不均匀会在复制集之间自动迁移达到均匀;迁移过程非常消耗IO -
也可以定制初始分片策略,使得每一个节点的数据均匀存储,不需要迁移
1.分片模式range和hash
2.必须定义分片键,以经常作为查询条件的列定义分片键,与定义索引列是一样的;分片键不可更改,而且分片键必须建索引,为Btree索引,分片键用于路由查询
3.range应用数据量级大的情况,hash分布数据更加均匀
RANGE分片配置及测试
# 激活数据库分片功能
mongo --port 38017 admin
admin> ( { enablesharding : "数据库名称" } )
eg:
admin> db.runCommand( { enablesharding : "test" } )
# 指定分片键对集合分片
### 创建索引
use test
> db.vast.ensureIndex( { id: 1 } ) //建索引
### 开启分片
use admin
> db.runCommand( { shardcollection : "test.vast",key : {id: 1} } ) //test库下vast表,分片键为id,1表示从小到大的顺序分布,-1表示从大到小的顺序分布
# 集合分片验证,录入数据
admin> use test
test> for(i=1;i<1000000;i++){ db.vast.insert({"id":i,"name":"shenzheng","age":70,"date":new Date()}); }
test> db.vast.stats()
# 分片结果测试
shard1:
mongo --port 38021
db.vast.count();
shard2:
mongo --port 38024
db.vast.count();
# Hash分片例子:
对oldboy库下的vast大表进行hash
创建哈希索引
(1)对于oldboy开启分片功能
mongo --port 38017 admin
admin> db.runCommand( { enablesharding : "oldboy" } )
(2)对于oldboy库下的vast表建立hash索引
use oldboy
oldboy> db.vast.ensureIndex( { id: "hashed" } )
(3)开启分片
use admin
admin > sh.shardCollection( "oldboy.vast", { id: "hashed" } )
(4)录入10w行数据测试
use oldboy
for(i=1;i<100000;i++){ db.vast.insert({"id":i,"name":"shenzheng","age":70,"date":new Date()}); }
(5)hash分片结果测试
mongo --port 38021
use oldboy
db.vast.count();
mongo --port 38024
use oldboy
db.vast.count();
分片集群的查询及管理
# 判断是否Shard集群
admin> db.runCommand({ isdbgrid : 1})
# 列出所有分片信息
admin> db.runCommand({ listshards : 1})
# 列出开启分片的数据库
admin> use config
config> db.databases.find( { "partitioned": true } )
或者:
config> db.databases.find() //列出所有数据库分片情况
# 查看分片的片键
config> db.collections.find().pretty()
{
"_id" : "test.vast",
"lastmodEpoch" : ObjectId("58a599f19c898bbfb818b63c"),
"lastmod" : ISODate("1970-02-19T17:02:47.296Z"),
"dropped" : false,
"key" : {
"id" : 1
},
"unique" : false
}
# 查看分片的详细信息
admin> sh.status()
# 删除分片节点(谨慎)
(1)确认blance是否在工作
sh.getBalancerState()
(2)删除shard2节点(谨慎)
mongos> db.runCommand( { removeShard: "shard2" } )
注意:删除操作一定会立即触发blancer。
balancer操作
# 介绍
mongos的一个重要功能,自动巡查所有shard节点上的chunk的情况,自动做chunk迁移。
什么时候工作?
1、自动运行,会检测系统不繁忙的时候做迁移
2、在做节点删除的时候,立即开始迁移工作
3、balancer只能在预设定的时间窗口内运行
有需要时可以关闭和开启blancer(备份的时候)
mongos> sh.stopBalancer()
mongos> sh.startBalancer()
# 自定义 自动平衡进行的时间段
https://docs.mongodb.com/manual/tutorial/manage-sharded-cluster-balancer/#schedule-the-balancing-window
连接到 mongos
mongo --port 38017
use config
sh.setBalancerState( true ) //开启balance的功能
db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "3:00", stop : "5:00" } } }, true )
sh.getBalancerWindow() //查看balance的时间窗口
sh.status()
关于集合的balancer(了解下)
关闭某个集合的balance
sh.disableBalancing("students.grades")
打开某个集合的balancer
sh.enableBalancing("students.grades")
确定某个集合的balance是开启或者关闭
db.getSiblingDB("config").collections.findOne({_id : "students.grades"}).noBalance;
13、备份恢复
-
备份恢复工具介绍
(1)** mongoexport/mongoimport
(2)***** mongodump/mongorestore -
备份工具区别在哪里?
应用场景总结:
-
mongoexport(导出)/mongoimport(导入) //导入导出的是Json格式 或者csv格式 ;可读性强,但体积大
(1)、异构平台迁移 mysql <---> mongodb
(2)、同平台,跨大版本:mongodb 低版本 ----> mongodb 高版本 -
mongodump(导出)/mongorestore(导入) //导入导出的是Bson格式;二进制文件,体积小,但是没有可读性
日常备份恢复时使用.
13.1 导出工具mongoexport
mongoexport具体用法如下所示:
$ mongoexport --help
参数说明:
-h:指明数据库宿主机的IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明collection的名字
-f:指明要导出那些列
-o:指明到要导出的文件名
-q:指明导出数据的过滤条件
--authenticationDatabase admin //用户的验证库
1.单表备份至json格式
mongoexport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log -o /mongodb/log.json
注:备份文件的名字可以自定义,默认导出了JSON格式的数据。
2. 单表备份至csv格式
如果我们需要导出CSV格式的数据,则需要使用----type=csv参数:
mongoexport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c oldguo --type=csv -f id,name,age,gender -o /mongodb/backup/log.csv
13.2 导入工具mongoimport
$ mongoimport --help
参数说明:
-h:指明数据库宿主机的IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明collection的名字
-f:指明要导入那些列
-j number //开启并发导入 ,数据量大使用 ,number为cpu数,默认为1,可以手动设定
数据恢复:
1.恢复json格式表数据到log1
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log1 /mongodb/backup/oldguo.json
2.恢复csv格式的文件到log2
上面演示的是导入JSON格式的文件中的内容,如果要导入CSV格式文件中的内容,则需要通过--type参数指定导入格式,具体如下所示:
错误的恢复
注意:
(1)csv格式的文件第一行,有列名字
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log2 --type=csv --headerline --file /mongodb/log.csv
//headerline:指明第一行是列名,不需要导入。
(2)csv格式的文件第一行,没有列名字
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log3 --type=csv -f id,name,age,date --file /mongodb/log.csv
13.3 异构平台迁移案例
# 案例1
mysql -----> mongodb
world数据库下city表进行导出,导入到mongodb
(1)mysql开启安全路径
vim /etc/my.cnf --->添加以下配置
secure-file-priv=/tmp
--重启数据库生效
/etc/init.d/mysqld restart
(2)导出mysql的city表数据
source /root/world.sql
select * from world.city into outfile '/tmp/city1.csv' fields terminated by ',';
terminated by ',' //分隔符替换成,
(3)处理备份文件
desc world.city
ID | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| CountryCode | char(3) | NO | MUL | | |
| District | char(20) | NO | | | |
| Population
vim /tmp/city.csv ----> 添加第一行列名信息
ID,Name,CountryCode,District,Population
(4)在mongodb中导入备份
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d world -c city --type=csv -f ID,Name,CountryCode,District,Population -j 4 /tmp/city1.csv
use world
db.city.find({CountryCode:"CHN"});
---------------------------------------------------------
# 案例2
world共100张表,全部迁移到mongodb
select table_name ,group_concat(column_name) from columns where table_schema='world' group by table_name;
select * from world.city into outfile '/tmp/world_city.csv' fields terminated by ',';
select concat("select * from ",table_schema,".",table_name ," into outfile '/tmp/",table_schema,"_",table_name,".csv' fields terminated by ',';")
from information_schema.tables where table_schema ='world';
导入:提示,使用infomation_schema.columns + information_schema.tables
mysql导出csv:
select * from test_info
into outfile '/tmp/test.csv'
fields terminated by ',' ------字段间以,号分隔
optionally enclosed by '"' ------字段用"号括起
escaped by '"' ------字段中使用的转义符为"
lines terminated by '\r\n'; ------行以\r\n结束
mysql导入csv:
load data infile '/tmp/test.csv'
into table test_info
fields terminated by ','
optionally enclosed by '"'
escaped by '"'
lines terminated by '\r\n';
13.4 mongodump和mongorestore
1、介绍
mongodump能够在Mongodb运行时进行备份,它的工作原理是对运行的Mongodb做查询,然后将所有查到的文档写入磁盘。
但是存在的问题时使用mongodump产生的备份不一定是数据库的实时快照,如果我们在备份时对数据库进行了写入操作,
则备份出来的文件可能不完全和Mongodb实时数据相等。另外在备份时可能会对其它客户端性能产生不利的影响。
2、mongodump用法如下:
$ mongodump --help
参数说明:
-h:指明数据库宿主机的IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明collection的名字
-o:指明到要导出的文件名
-q:指明导出数据的过滤条件
-j, number (4 by default) //并发
--oplog 备份的同时备份oplog,配置复制集使用
3、mongodump和mongorestore基本使用
mongodump 工具
# 全库备份
mkdir /mongodb/backup
mongodump -uroot -proot123 --port 27017 --authenticationDatabase admin -o /mongodb/backup
备份完有bson和 json两种格式,bson为二进制格式,无法读;
bsondump t100w.bson //bsondump工具,将bson格式文件转换成 json格式文件
bsondump t100w.bson > /tmp/t100w.json
# 备份world库
$ mongodump -uroot -proot123 --port 27017 --authenticationDatabase admin -d world -o /mongodb/backup/
# 备份oldboy库下的log集合
$ mongodump -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log -o /mongodb/backup/
# 压缩备份
$ mongodump -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldguo -o /mongodb/backup/ --gzip
mongodump -uroot -proot123 --port 27017 --authenticationDatabase admin -o /mongodb/backup/ --gzip
$ mongodump -uroot -proot123 --port 27017 --authenticationDatabase admin -d app -c vast -o /mongodb/backup/ --gzip、
mongorestore 恢复工具
一般是发生故障时,使用mongorestore恢复单库、单副本集,会覆盖原有数据
# 恢复world库
$ mongorestore -uroot -proot123 --port 27017 --authenticationDatabase admin -d world1 /mongodb/backup/world //注意:恢复单库,必须指定到要恢复的库名路径下
# 恢复oldguo库下的t1集合
[mongod@db03 oldboy]$ mongorestore -uroot -proot123 --port 27017 --authenticationDatabase admin -d world -c t1 --gzip /mongodb/backup.bak/oldboy/log1.bson.gz //恢复单副本集、必须指定到文件名;备份时压缩,恢复也要加上--gzip参数
# drop表示恢复的时候把之前的集合drop掉(危险)
$ mongorestore -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy --drop /mongodb/backup/oldboy
14、mongodump和mongorestore高级企业应用(--oplog)
- 注意:--oplog 只能在replica set(复制集)或者master/slave模式用
14.1 oplog介绍
-
oplog为mongodb自带的日志,类似于mysql的binlog;有了oplog备份就可以采用热备功能,可以把数据快照备份,也可以把备份过程中发生的变化一并保存下来。
在replica set中oplog是一个定容集合(capped collection),它的默认大小是磁盘空间的5%(可以通过--oplogSizeMB参数修改)。 -
位于local库的db.oplog.rs,有兴趣可以看看里面到底有些什么内容。
其中记录的是整个mongod实例一段时间内数据库的所有变更(插入/更新/删除)操作。
当空间用完时新记录自动覆盖最老的记录。
其覆盖范围被称作oplog时间窗口。需要注意的是,因为oplog是一个定容集合,
所以时间窗口能覆盖的范围会因为你单位时间内的更新次数不同而变化。
想要查看当前的oplog时间窗口预计值,可以使用以下命令:
mongod -f /mongodb/28017/conf/mongod.conf
mongod -f /mongodb/28018/conf/mongod.conf
mongod -f /mongodb/28019/conf/mongod.conf
mongod -f /mongodb/28020/conf/mongod.conf
# 查看oplog定容集合内容:
use local
db.oplog.rs.find().pretty()
"ts" : Timestamp(1553597844, 1), //时间戳,数字表示这一秒发生的第几个操作
"op" : "n" //命令的类型
"o" : //具体信息
"i": insert
"u": update
"d": delete
"c": db cmd //库级别的命令;删库,建表,删表
例:db.oplog.rs.find({"op":"c"}).pretty() //查看oplog集合中op为c的信息
# 查看oplog集合覆盖窗口信息
test:PRIMARY> rs.printReplicationInfo()
configured oplog size: 1561.5615234375MB <--集合大小
log length start to end: 423849secs (117.74hrs) <--预计窗口覆盖时间
oplog first event time: Wed Sep 09 2015 17:39:50 GMT+0800 (CST)
oplog last event time: Mon Sep 14 2015 15:23:59 GMT+0800 (CST)
now: Mon Sep 14 2015 16:37:30 GMT+0800 (CST)
14.2 oplog企业级应用
(1)实现热备,在备份时使用--oplog选项
注:为了演示效果我们在备份过程,模拟数据插入
(2)准备测试数据
[mongod@db01 conf]$ mongo --port 28018
use oldboy
for(var i = 1 ;i < 100; i++) {
db.foo.insert({a:i});
}
my_repl:PRIMARY> db.oplog.rs.find({"op":"i"}).pretty()
# oplog 配合mongodump实现全备热备
mongodump --port 28018 --oplog -o /mongodb/backup
作用介绍:--oplog 会记录备份过程中的数据变化。会以oplog.bson保存下来
# 全备恢复
mongorestore --port 28018 --drop --oplogReplay /mongodb/backup
--drop 将重复的数据删除,不加此参数会报错
14.3 oplog高级应用
背景:每天0点全备,oplog恢复窗口为48小时
某天,上午10点world.city 业务表被误删除。
恢复思路:
0、停应用
2、找测试库
3、恢复昨天晚上全备
4、截取全备之后到world.city误删除之间时间的oplog,并恢复到测试库
5、将误删除表导出,恢复到生产库
恢复步骤:
模拟故障环境:
1、全备数据库
模拟原始数据
mongo --port 28017
use wo
for(var i = 1 ;i < 20; i++) {
db.ci.insert({a: i});
}
全备:
rm -rf /mongodb/backup/*
mongodump --port 28018 --oplog -o /mongodb/backup
--oplog功能:在备份同时,将备份过程中产生的日志进行备份
文件必须存放在/mongodb/backup下,自动命令为oplog.bson
再次模拟数据
db.ci1.insert({id:1})
db.ci2.insert({id:2})
2、上午10点:删除wo库下的ci表
10:00时刻,误删除
db.ci.drop()
show tables;
3、备份现有的oplog.rs表
mongodump --port 28018 -d local -c oplog.rs -o /mongodb/
ls /mongodb/local/
备份出来的文件记录了所有的日志,它有幂等性,会跳过已有的日志
4、截取oplog并恢复到drop之前的位置
更合理的方法:登陆到原数据库
[mongod@db03 local]$ mongo --port 28018
my_repl:PRIMARY> use local
db.oplog.rs.find({op:"c"}).pretty();
{
"ts" : Timestamp(1553659908, 1),
"t" : NumberLong(2),
"h" : NumberLong("-7439981700218302504"),
"v" : 2,
"op" : "c",
"ns" : "wo.$cmd",
"ui" : UUID("db70fa45-edde-4945-ade3-747224745725"),
"wall" : ISODate("2019-03-27T04:11:48.890Z"),
"o" : {
"drop" : "ci"
}
}
获取到oplog误删除时间点位置:
"ts" : Timestamp(1553659908, 1)
5、恢复备份+应用oplog
思路:将oplog.rs日志的备份拷贝到全备目录,重命名为oplog.bson,然后全备恢复,会自动读取oplog.bson,跳过错误操作,恢复数据
[mongod@db03 backup]$ cd /mongodb/local/
[mongod@db03 local]$ ls
oplog.rs.bson oplog.rs.metadata.json
[mongod@db03 local]$ cp oplog.rs.bson /mongodb/backup/
cd /mongodb/backup/
mv oplog.rs.bson oplog.bson
# 恢复全备
mongorestore --port 38021 --oplogReplay --oplogLimit "1553659908:1" --drop /mongodb/backup/
--oplogReplay //重演oplog.bson
--oplogLimit "1553659908:1" //跳过错误操作
15、分片集群的备份思路(了解)
-
你要备份什么?
config server
shard 节点 -
备份有什么困难和问题
(1)chunk迁移的问题
人为控制在备份的时候,避开chunk迁移的时间窗口
(2)shard节点之间的数据不在同一时间点。
保证节点数据时静止时分片集群备份,同一时间点,用脚本将每个复制集去掉一个节点(rs.remove 节点名),数据就会静止;就可以做一致性备份;备份完再将节点加上去
Ops Manager