“这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战”
NoSQL 数据库四大家族:
- 列存储:Hbase
- 键值(Key-Value)存储:Redis
- 图像存储:Neo4J
- 文档存储:MongoDB,ES
NoSQL 的优势:
- 高可扩展性
- 分布式计算
- 没有复杂的关系
- 低成本
- 架构灵活
- 半结构化数据
1. 逻辑结构
| MongoDB 逻辑结构 | MySQL 逻辑结构 |
|---|---|
| 库(database) | 库 |
| 集合(collection) | 表 |
| 文档(document) | 行 |
2. 安装部署
2.1 系统准备
- Redhat 或 centos6.2 以上系统
# cat /etc/issue
# cat /proc/version
# cat /etc/redhat-release
-
系统开发包完整
-
ip 地址和 hosts 文件解析正常
-
iptables 防火墙 & SELinux 关闭
-
关闭大页内存机制
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
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag
其他系统关闭参照官方文档:
2.2 Mongodb 安装
2.2.1 创建所需用户和组
# useradd mongod
# passwd mongod
2.2.2 创建 mongodb 所需目录结构
[root@VM-0-3-centos ~]# mkdir -p /mongodb/conf
[root@VM-0-3-centos ~]# mkdir -p /mongodb/log
[root@VM-0-3-centos ~]# mkdir -p /mongodb/data
2.2.3 上传并解压文件到指定位置
[root@VM-0-3-centos software]# tar xf mongodb-linux-x86_64-3.6.22.tgz
[root@VM-0-3-centos software]# cp -r mongodb-linux-x86_64-3.6.22/bin/ /mongodb/
2.2.4 设置目录结构权限
[root@VM-0-3-centos mongodb]# chown -R mongod.mongod /mongodb/
2.2.5 设置用户环境变量
[root@VM-0-3-centos mongodb]# su - mongod
[mongod@VM-0-3-centos ~]$ vim .bash_profile
export PATH=/mongodb/bin:$PATH
[mongod@VM-0-3-centos ~]$ source .bash_profile
2.2.6 启动 mongodb
[mongod@VM-0-3-centos ~]$ mongod --dbpath=/mongodb/data --logpath=/mongodb/log/mongodb.log --port=27017 --logappend --fork
about to fork child process, waiting until server is ready for connections.
forked process: 9622
child process started successfully, parent exiting
2.2.7 登录 mongodb
[mongod@VM-0-3-centos ~]$ mongo
MongoDB shell version v3.6.22
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("5dc425e8-005d-4172-9ce7-f7b097f94988") }
MongoDB server version: 3.6.22
......
2.2.8 使用配置文件
配置文件使用 YAML 格式。
注意:YAML 格式不支持 tab 键,使用空格代替。
--系统日志有关
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: 172.21.0.3,127.0.0.1
EOF
2.2.9 使用配置文件停止启动
[mongod@VM-0-3-centos conf]$ mongod -f /mongodb/conf/mongo.conf --shutdown
killing process with pid: 9622
[mongod@VM-0-3-centos conf]$ mongod -f /mongodb/conf/mongo.conf
about to fork child process, waiting until server is ready for connections.
forked process: 17560
child process started successfully, parent exiting
2.2.10 mongodb 使用 systemd 管理
[root@VM-0-3-centos ~]# 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@VM-0-3-centos ~]# systemctl restart mongod
[root@VM-0-3-centos ~]# systemctl stop mongod
[root@VM-0-3-centos ~]# systemctl start mongod
3. mongodb 常用基本操作
3.1 mongodb 默认存在的库
- 登录时默认存在的库:
> db
test
-
管理 mongodb 有关的系统库
- admin:系统预留库,mongodb 系统管理库
- local:本地预留库,存储关键日志
- config:mongodb 配置信息库
> show databases;
admin 0.000GB
config 0.000GB
local 0.000GB
3.2 命令种类
3.2.1 db 对象相关命令
db.[tab][tab]
db.help()
db.admin.[tab][tab]
db.admin.help()
3.2.2 rs 复制集有关(replication set)
rs.[tab][tab]
rs.help()
3.2.3 sh 分片集群(sharding cluster)
sh.[tab][tab]
sh.help()
4. mongodb 对象操作
| mongo | mysql |
|---|---|
| 库 | 库 |
| 集合 | 表 |
| 文档 | 数据行 |
4.1 库操作
> use test
> db.dropDatabase()
{ "ok" : 1 }
4.2 集合的操作
> db.createCollection('a')
{ "ok" : 1 }
> db.createCollection('b')
{ "ok" : 1 }
> db.a.insert({name:"zhangsan"})
WriteResult({ "nInserted" : 1 })
> db.b.insert({id:101,name:"zhangsan",age:20,gender:"m"})
WriteResult({ "nInserted" : 1 })
> show tables
a
b
> db.b.insert({id:102,name:"lisi"})
WriteResult({ "nInserted" : 1 })
> db.b.insert({a:"a",b:"b"})
WriteResult({ "nInserted" : 1 })
> db.b.insert({a:1,b:2})
WriteResult({ "nInserted" : 1 })
4.3 文档操作
- 数据录入:
for(i=0;i<10000;i++){db.log.insert({"uid":i,"name":"mongodb","age":6,"date":new Date()})}
- 查询数据行数:
> db.log.count()
10000
- 全表查询:
> db.log.find()
{ "_id" : ObjectId("6030ca7a5f3b546582079dcc"), "uid" : 0, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.706Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dcd"), "uid" : 1, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.747Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dce"), "uid" : 2, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.747Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dcf"), "uid" : 3, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.748Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd0"), "uid" : 4, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.749Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd1"), "uid" : 5, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.749Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd2"), "uid" : 6, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.751Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd3"), "uid" : 7, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.751Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd4"), "uid" : 8, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.752Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd5"), "uid" : 9, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.752Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd6"), "uid" : 10, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.753Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd7"), "uid" : 11, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.753Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd8"), "uid" : 12, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.754Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dd9"), "uid" : 13, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.754Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dda"), "uid" : 14, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.754Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079ddb"), "uid" : 15, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.755Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079ddc"), "uid" : 16, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.755Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079ddd"), "uid" : 17, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.756Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079dde"), "uid" : 18, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.756Z") }
{ "_id" : ObjectId("6030ca7a5f3b546582079ddf"), "uid" : 19, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:18.756Z") }
Type "it" for more
- 每页显示 50 条记录:
> DBQuery.shellBatchSize=50;
- 按照条件查询
> db.log.find({uid:999})
{ "_id" : ObjectId("6030ca7b5f3b54658207a1b3"), "uid" : 999, "name" : "mongodb", "age" : 6, "date" : ISODate("2021-02-20T08:38:19.091Z") }
- 以标准的 json 格式显示数据
> db.log.find({uid:999}).pretty()
{
"_id" : ObjectId("6030ca7b5f3b54658207a1b3"),
"uid" : 999,
"name" : "mongodb",
"age" : 6,
"date" : ISODate("2021-02-20T08:38:19.091Z")
}
- 删除集合中所有记录
> db.log.remove({})
WriteResult({ "nRemoved" : 10000 })
- 查询集合存储信息
> db.log.totalSize() //集合中索引+数据压缩存储之后的大小
364544
5. 用户及权限管理
5.1 注意事项
- 验证库:建立用户时 use 到的库,在使用用户时,要加上验证库才能登陆。
对于管理员用户,必须在 admin 下创建。
- 建用户时,use 到的库,就是此用户的验证库
- 登录时,必须明确指定验证库才能登录
- 通常,管理员用的验证库是 admin,普通用户的验证库一般是所管理的库设置为验证库
- 如果直接登录到数据库,不进行 use,默认的验证库是 test,不是我们生产建议的。
- 从 3.6 版本开始,不添加 bindIp 参数,默认不让远程登录,只能本地管理员登录。
5.2 用户创建语法
use admin
db.createUser
{
user: "<name>",
pwd: "<cleartext password>",
roles: [
{ role: "<role>",
db: "<database>" } | "<role>",
...
]
}
基本语法说明:
- user:用户名
- pwd:密码
- roles:
- role:角色名
- db:作用对象
- role:root,readWrite,read
验证数据库:
mongo -u oldboy -p 123 10.0.0.53/oldboy
5.3 用户管理例子
5.3.1 创建超级管理员
创建超级管理员:管理所有数据库(注意:必须 use admin 再去创建)
$ mongo
use admin
db.createUser(
{
user: "root",
pwd: "123",
roles: [ { role: "root", db: "admin" } ]
}
)
> db.createUser(
... {
... user: "root",
... pwd: "123",
... roles: [ { role: "root", db: "admin" } ]
... }
... )
Successfully added user: {
"user" : "root",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
5.3.2 验证用户
> db.auth('root','123')
1
5.3.3 配置文件中加入如下配置:
security:
authorization: enabled
5.3.4 重启 mongodb
mongod -f /mongodb/conf/mongo.conf --shutdown
mongod -f /mongodb/conf/mongo.conf
5.3.5 登录验证
[mongod@VM-0-3-centos ~]$ mongo -uroot -p123 admin
[mongod@VM-0-3-centos ~]$ mongo -uroot -p123 172.21.0.3/admin
[mongod@VM-0-3-centos ~]$ mongo -uroot -p123 //本地登录可以正常登录
[mongod@VM-0-3-centos ~]$ mongo -uroot -p123 172.21.0.3 //远程无法登录,少了验证库
或者使用 mongo 登录之后验证
[mongod@VM-0-3-centos ~]$ mongo
> use admin
switched to db admin
> db.auth('root','123')
1
5.3.6 查看用户
> use admin
switched to db admin
> show tables
system.users
system.version
> db.system.users.find().pretty()
{
"_id" : "admin.root",
"userId" : UUID("b66a23d0-622f-46e6-b469-176fcaab3027"),
"user" : "root",
"db" : "admin",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "7m3wt0KwysDD2cuFuan2sA==",
"storedKey" : "WC1qZ7TESG3DJYwNKcaChYF3mL0=",
"serverKey" : "imIiBscUI88xubZbtYd5+TLyUBM="
}
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
5.3.7 创建应用用户,创建一个对 wys 库的可读、可写用户
use wys
db.createUser(
{
user: "app01",
pwd: "app01",
roles: [ { role: "readWrite" , db: "wys" } ]
}
)
[mongod@VM-0-3-centos ~]$ mongo -uapp01 -papp01 wys
5.3.8 查询 mongodb 中的用户信息
[mongod@VM-0-3-centos ~]$ mongo -uroot -p123 172.21.0.3/admin
> db.system.users.find().pretty()
{
"_id" : "admin.root",
"userId" : UUID("b66a23d0-622f-46e6-b469-176fcaab3027"),
"user" : "root",
"db" : "admin",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "7m3wt0KwysDD2cuFuan2sA==",
"storedKey" : "WC1qZ7TESG3DJYwNKcaChYF3mL0=",
"serverKey" : "imIiBscUI88xubZbtYd5+TLyUBM="
}
},
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
{
"_id" : "wys.app01",
"userId" : UUID("72cb4ea8-b999-4abf-9c87-5944fa6d64e4"),
"user" : "app01",
"db" : "wys",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "ovemgKbDzgwcOFV+VGAPuQ==",
"storedKey" : "ig9qiJjvnYB8P7H3I4wi6OaFtYY=",
"serverKey" : "pUD7U2p03eank24tdXy2hIbP4EM="
}
},
"roles" : [
{
"role" : "readWrite",
"db" : "wys"
}
]
}
5.3.9 创建对 app 数据库读写权限的用户并对 test 数据库具有读权限的用户
use app
db.createUser(
{
user: "app01",
pwd: "app01",
roles: [
{ role: "readWrite" , db: "wys" },
{ role: "read" , db: "test" },
]
}
)
5.4 删除用户(root 用户登录,use 到验证库)
>use app
switched to db app
> db.dropUser("app01")
true
6. MongoDB 复制集 RS(Replication Set)
6.1 基本原理
基本构成是 1 主 2 从的结构,自带互相监控投票机制(Raft(MongoDB)、Paxos(mysql MGR 用的是变种))。
如果发生主库宕机,复制集内部会进行投票选举,选择一个新的主库替代原有主库对外提供服务。同时复制集会自动通知客户端程序,主库已经发生切换了。应用就会连接到新的主库。
6.2 Replication Set 配置过程详解
6.2.1 规划
三个以上的 mongodb 节点(或多实例)
6.2.2 环境准备
多个端口
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: 172.21.0.3,127.0.0.1
port: 28017
replication:
oplogSizeMB: 2048
replSetName: my_repl
EOF
[mongod@VM-0-3-centos conf]$ cp /mongodb/28017/conf/mongod.conf /mongodb/28018/conf/
[mongod@VM-0-3-centos conf]$ cp /mongodb/28017/conf/mongod.conf /mongodb/28019/conf/
[mongod@VM-0-3-centos conf]$ cp /mongodb/28017/conf/mongod.conf /mongodb/28020/conf/
[mongod@VM-0-3-centos conf]$ sed 's#28017#28018#g' /mongodb/28018/conf/mongod.conf -i
[mongod@VM-0-3-centos conf]$ sed 's#28017#28019#g' /mongodb/28019/conf/mongod.conf -i
[mongod@VM-0-3-centos conf]$ sed 's#28017#28020#g' /mongodb/28020/conf/mongod.conf -i
配置文件介绍
-
wireTiger:存储引擎
- CacheSizeGB:1(相当于 mysql buffer pool size)
-
replication:复制集相关
- oplogSizeMB:2048(MongoDB 是从表中读取数据,给表分配的空间大小。默认是总容量的 5%)
- replSetName:复制集设置的名称
启动多个实例备用
[mongod@VM-0-3-centos conf]$ mongod -f /mongodb/28017/conf/mongod.conf
[mongod@VM-0-3-centos conf]$ mongod -f /mongodb/28018/conf/mongod.conf
[mongod@VM-0-3-centos conf]$ mongod -f /mongodb/28019/conf/mongod.conf
[mongod@VM-0-3-centos conf]$ mongod -f /mongodb/28020/conf/mongod.conf
[mongod@VM-0-3-centos conf]$ netstat -lnp|grep 280
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 127.0.0.1:28018 0.0.0.0:* LISTEN 23796/mongod
tcp 0 0 172.21.0.3:28018 0.0.0.0:* LISTEN 23796/mongod
tcp 0 0 127.0.0.1:28019 0.0.0.0:* LISTEN 23835/mongod
tcp 0 0 172.21.0.3:28019 0.0.0.0:* LISTEN 23835/mongod
tcp 0 0 127.0.0.1:28020 0.0.0.0:* LISTEN 23878/mongod
tcp 0 0 172.21.0.3:28020 0.0.0.0:* LISTEN 23878/mongod
tcp 0 0 127.0.0.1:28017 0.0.0.0:* LISTEN 23739/mongod
tcp 0 0 172.21.0.3:28017 0.0.0.0:* LISTEN 23739/mongod
unix 2 [ ACC ] STREAM LISTENING 55004334 23739/mongod /tmp/mongodb-28017.sock
unix 2 [ ACC ] STREAM LISTENING 55004533 23796/mongod /tmp/mongodb-28018.sock
unix 2 [ ACC ] STREAM LISTENING 55004582 23835/mongod /tmp/mongodb-28019.sock
unix 2 [ ACC ] STREAM LISTENING 55004652 23878/mongod /tmp/mongodb-28020.sock
6.3 配置普通复制集
1 主 2 从,从库是普通从库
- 搭建
mongo --port 28017 admin
config = {_id: 'my_repl', members: [
{_id: 0, host: '172.21.0.3:28017'},
{_id: 1, host: '172.21.0.3:28018'},
{_id: 2, host: '172.21.0.3:28019'}]
}
rs.initiate(config)
- 查询复制集状态
rs.status();
主库挂掉之后,自动故障恢复。
主库挂掉再恢复之后,会变成从库。
6.4 1 主 1 从 1 个 arbiter
mongo -port 28017 admin
config = {_id: 'my_repl', members: [
{_id: 0, host: '172.21.0.3:28017'},
{_id: 1, host: '172.21.0.3:28018'},
{_id: 2, host: '172.21.0.3:28019',"arbiterOnly":true}]
}
rs.initiate(config)
6.5 复制集集中管理
6.5.1 查看复制集状态
rs.status():查看整体复制集状态rs.isMaster():查看当前是否是主节点rs.conf():查看复制集配置信息
6.5.2 添加删除节点
arbiter 节点设置:
- 重新搭建
- 将想要设置成 arbiter 的节点删除,然后再加进去
rs.remove("ip:port"):删除一个节点rs.add("ip:port"):新增从节点rs.addArb("ip:port"):新增仲裁节点
示例:
my_repl:PRIMARY> rs.remove("172.21.0.3:28019")
{
"ok" : 1,
"operationTime" : Timestamp(1613984891, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1613984891, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
my_repl:PRIMARY> rs.addArb("172.21.0.3:28019")
{
"ok" : 1,
"operationTime" : Timestamp(1613985032, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1613985032, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
my_repl:PRIMARY> rs.config()
...
{
"_id" : 2,
"host" : "172.21.0.3:28019",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
...
6.5.3 特殊从节点
介绍
- arbiter 节点:主要负责选主过程中的投票,但是不存储任何数据,也不提供任何服务
- hidden 节点:隐藏节点不参与选主,也不对外提供服务。
- delay 节点:延时节点,数据落后主库一段时间,因为数据是延时的,也不应该提供服务或参与选主,所以通常都会配合 hidden(隐藏)
一般情况下会将 delay + hidden 一起配置使用
配置延时节点(一般延时节点也配置成 hidden)
cfg=rs.conf()
cfg.members[2].priority=0
cfg.members[2].hidden=true
cfg.members[2].slaveDelay=120
rs.reconfig(cfg)
注意 members 的下标并不是 re.config() 中 members 列表的 id(一开始是,但是如果删除节点了,那个节点的下标就没了,新添加节点会继续往后添加)。所以下标应该是从第一个开始数,0,1,2 ......
- 取消以上配置
cfg=rs.conf()
cfg.members[2].priority=1
cfg.members[2].hidden=false
cfg.members[2].slaveDelay=0
rs.reconfig(cfg)
- 配置成功后,通过以下命令查询配置后的属性
rs.conf();
7. MongoDB Sharding Cluster 分片集群
7.1 规划
共 10 个实例:38017 - 38026
-
config server:38018 - 38020
- 3 台构成的复制集(1 主 2 从,不支持 arbiter)38018 - 38030(复制集名字 configsvr)
-
shard 节点:
- sh1:38021 - 38023(1 主 2 从,其中一个节点为 arbiter,复制集名字 sh1)
- sh2:38024 - 38026(1 主 2 从,其中一个节点为 arbiter,复制集名字 sh2)
-
mongos:38017
7.2 Shard 节点配置过程
7.2.1 目录创建
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
7.2.2 修改配置文件
第一组复制集搭建:21-23(1 主 1 从 1 Arb)
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: 172.21.0.3,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 从 1 Arb)
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: 172.21.0.3,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
7.2.3 启动所有节点,并搭建复制集
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
[mongod@VM-0-3-centos conf]$ mongo --port 38021
use admin
config = {_id: 'sh1', members: [
{_id: 0, host: '172.21.0.3:38021'},
{_id: 1, host: '172.21.0.3:38022'},
{_id: 2, host: '172.21.0.3:38023',"arbiterOnly":true}]
}
rs.initiate(config)
[mongod@VM-0-3-centos conf]$ mongo --port 38024
use admin
config = {_id: 'sh2', members: [
{_id: 0, host: '172.21.0.3:38024'},
{_id: 1, host: '172.21.0.3:38025'},
{_id: 2, host: '172.21.0.3:38026',"arbiterOnly":true}]
}
rs.initiate(config)
7.3 config 节点配置
7.3.1 目录创建
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
7.3.2 修改配置文件
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: 172.21.0.3,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
7.3.3 启动节点,并配置复制集
mongod -f /mongodb/38018/conf/mongodb.conf
mongod -f /mongodb/38019/conf/mongodb.conf
mongod -f /mongodb/38020/conf/mongodb.conf
mongo --port 38018
config = {_id: 'configReplSet', members: [
{_id: 0, host: '172.21.0.3:38018'},
{_id: 1, host: '172.21.0.3:38019'},
{_id: 2, host: '172.21.0.3:38020'}]
}
rs.initiate(config)
注:configserver 可以是一个节点,官方建议复制集。configserver 不能有 arbiter。
新版本中,要求必须是复制集。
注:mongodb 3.4 之后,虽然要求 config server 为replica set,但是不支持 arbiter。
7.4 mongos 节点配置
7.4.1 创建目录
[mongod@VM-0-3-centos conf]$ 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: 172.21.0.3,127.0.0.1
port: 38017
sharding:
configDB: configReplSet/172.21.0.3:38018,172.21.0.3:38019,172.21.0.3:38020
processManagement:
fork: true
EOF
7.4.3 启动 mongos
mongos -f /mongodb/38017/conf/mongos.conf
7.5 Sharding Cluster 架构

7.6 分片集群添加节点
连接到其中一个 mongos(172.21.0.3),做以下配置:
-
连接到 mongos 的 admin 数据库
su - mongodmongo 172.21.0.3:38017/admin
-
添加分片
db.runCommand( { addshard : "sh1/172.21.0.3:38021,172.21.0.3:38022,172.21.0.3:38023",name:"shard1"} )db.runCommand( { addshard : "sh2/172.21.0.3:38024,172.21.0.3:38025,172.21.0.3:38026",name:"shard2"} )
-
列出分片
db.runCommand( { listshards : 1 } )
-
整体状况查看
sh.status()
7.7 使用分片集群
7.7.1 range 分片及测试
1. 激活数据库分片功能
mongo --port 38017 admin
admin> ( { enablesharding : "数据库名称" } )
eg:
admin> db.runCommand( { enablesharding : "test" } )
2. 指定分片键对集合分片
### 创建索引
use test
> db.vast.ensureIndex( { id: 1 } )
### 开启分片
use admin
> db.runCommand( { shardcollection : "test.vast",key : {id: 1} } )
3. 集合分片验证
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()
4. 分片结果测试
shard1:
mongo --port 38021
db.vast.count();
shard2:
mongo --port 38024
db.vast.count();
7.7.2 Hash 分片例子
对 oldboy 库下的 vast 大表进行 hash,创建哈希索引。
-
对于 oldboy 开启分片功能
mongo --port 38017 adminuse admindb.runCommand( { enablesharding : "oldboy" } )
-
对于 oldboy 库下的 vast 表建立 hash 索引
db.vast.ensureIndex( { id: "hashed" } )
-
开启分片
use adminsh.shardCollection( "oldboy.vast", { id: "hashed" } )
-
录入 10w 行数据测试
use oldboyfor(i=1;i<100000;i++){ db.vast.insert({"id":i,"name":"shenzheng","age":70,"date":new Date()}); }
-
hash 分片结果测试
mongo --port 38021use oldboydb.vast.count();mongo --port 38024use oldboydb.vast.count();
7.8 分片集群的查询及管理
7.8.1 判断是否 Shard 集群
admin> db.runCommand({ isdbgrid : 1})
7.8.2 列出所有分片信息
admin> db.runCommand({ listshards : 1})
7.8.3 列出开启分片的数据库
admin> use config
config> db.databases.find( { "partitioned": true } )
或者:
config> db.databases.find() //列出所有数据库分片情况
7.8.4 查看分片的片键
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
}
7.8.5 查看分片的详细信息
admin> sh.status()
7.8.6 删除分片节点(谨慎)
(1)确认blance是否在工作
sh.getBalancerState()
(2)删除shard2节点(谨慎)
mongos> db.runCommand( { removeShard: "shard2" } )
注意:删除操作一定会立即触发blancer。
7.9 balancer 操作
7.9.1 介绍
mongos 的一个重要功能,自动巡查所有 shard 节点上的 chunk 的情况,自动做 chunk 迁移。
什么时候工作?
- 自动运行,会检测系统不繁忙的时候做迁移
- 在做节点删除的时候,立即开始迁移工作
- balancer 只能在预设定的时间窗口内运行
有需要时可以关闭和开启 blancer(备份的时候)
mongos> sh.stopBalancer()
mongos> sh.startBalancer()
7.9.2 自定义自动平衡进行的时间段
https://docs.mongodb.com/manual/tutorial/manage-sharded-cluster-balancer/#schedule-the-balancing-window
// connect to mongos
use config
sh.setBalancerState( true )
db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "3:00", stop : "5:00" } } }, true )
sh.getBalancerWindow()
sh.status()
关于集合的 balancer(了解下)
关闭某个集合的 balance
sh.disableBalancing("students.grades")
打开某个集合的 balancer
sh.enableBalancing("students.grades")
确定某个集合的 balance 是开启或者关闭
db.getSiblingDB("config").collections.findOne({_id : "students.grades"}).noBalance;
8. 备份恢复
8.1 备份恢复工具介绍
- mongoexport/mongoimport
- mongodump/mongorestore
8.2 备份工具区别在哪里
8.2.1 格式
- mongoexport/mongoimport:导入/导出的是 JSON 格式或者是 CSV 格式。
- mongodump/mongorestore:导入/导出的是 BSON 格式。
8.2.2 可读性
JSON 可读性强但体积较大,BSON 则是二进制文件,体积小但对人类几乎没有可读性。
8.2.3 选择
在一些 mongodb 版本之间,BSON 格式可能会随版本不同而有所不同,所以不同版本之间用 mongodump/mongorestore 可能不会成功,具体要看版本之间的兼容性。当无法使用 BSON 进行跨版本的数据迁移的时候,使用 JSON 格式即 mongoexport/mongoimport 是一个可选项。
跨版本的 mongodump/mongorestore 个人并不推荐,实在要做请先检查文档看两个版本是否兼容(大部分情况是的)
应用场景总结:
-
mongoexport/mongoimport:json csv
- 异构平台迁移:mysql <---> mongodb
- 同平台,跨大版本:mongodb 2 ----> mongodb 3
-
mongodump/mongorestore
- 日常备份恢复时使用
8.2.4 特殊点
JSON 虽然具有较好的跨版本通用性,但其只保留了数据部分,不保留索引,账户等其他基本信息。使用时应该注意。
8.3 导出工具 mongoexport
mongoexport 具体用法如下所示:
$ mongoexport --help
参数说明:
- -h:指明数据库宿主机的 IP
- -u:指明数据库的用户名
- -p:指明数据库的密码
- -d:指明数据库的名字
- -c:指明 collection 的名字
- -f:指明要导出那些列
- -o:指明到要导出的文件名
- -q:指明导出数据的过滤条件
- --authenticationDatabase admin
- 单表备份至 json 格式
mongoexport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log -o /mongodb/log.json
注:备份文件的名字可以自定义,默认导出了 JSON 格式的数据。
- 单表备份至 csv 格式
如果我们需要导出 CSV 格式的数据,则需要使用 ----type=csv 参数:
mongoexport -uroot -proot123 --port 27017 --authenticationDatabase admin -d test -c log --type=csv -f uid,name,age,date -o /mongodb/log.csv
8.4 导入工具 mongoimport
$ mongoimport --help
参数说明:
- -h:指明数据库宿主机的 IP
- -u:指明数据库的用户名
- -p:指明数据库的密码
- -d:指明数据库的名字
- -c:指明 collection 的名字
- -f:指明要导入那些列
- -j, --numInsertionWorkers= number of insert operations to run concurrently (defaults to 1)
//并行
数据恢复:
- 恢复 json 格式表数据到 log1
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log1 /mongodb/log.json
- 恢复 csv 格式的文件到 log2
上面演示的是导入 JSON 格式的文件中的内容,如果要导入 CSV 格式文件中的内容,则需要通过 --type 参数指定导入格式,具体如下所示:
错误的恢复
注意:
- csv 格式的文件头行,有列名字
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log2 --type=csv --headerline --file /mongodb/log.csv
- csv 格式的文件头行,没有列名字
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy -c log3 --type=csv -f id,name,age,date --file /mongodb/log.csv
--headerline:指明第一行是列名,不需要导入。
8.5 异构平台迁移案例
mysql -----> mongodb
world 数据库下 city 表进行导出,导入到 mongodb
- mysql 开启安全路径
vim /etc/my.cnf --->添加以下配置
secure-file-priv=/tmp
--重启数据库生效
/etc/init.d/mysqld restart
- 导出 mysql 的 city 表数据
source /root/world.sql
select * from world.city into outfile '/tmp/city1.csv' fields terminated by ',';
- 处理备份文件
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
- 在 mongodb 中导入备份
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d world -c city --type=csv -f ID,Name,CountryCode,District,Population --file /tmp/city1.csv
use world
db.city.find({CountryCode:"CHN"});
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';
8.6 mongodump 和 mongorestore
8.6.1 介绍
mongodump 能够在 Mongodb 运行时进行备份,它的工作原理是对运行的 Mongodb 做查询,然后将所有查到的文档写入磁盘。
但是存在的问题时使用 mongodump 产生的备份不一定是数据库的实时快照,如果我们在备份时对数据库进行了写入操作,则备份出来的文件可能不完全和 Mongodb 实时数据相等。另外在备份时可能会对其它客户端性能产生不利的影响。
8.6.2 mongodump 用法如下
$ mongodump --help
参数说明:
- -h:指明数据库宿主机的 IP
- -u:指明数据库的用户名
- -p:指明数据库的密码
- -d:指明数据库的名字
- -c:指明 collection 的名字
- -o:指明到要导出的文件名
- -q:指明导出数据的过滤条件
- -j, --numParallelCollections= number of collections to dump in parallel (4 by default)
- --oplog 备份的同时备份 oplog
8.6.3 mongodump 和 mongorestore 基本使用
全库备份
$ mongodump -uroot -proot123 --port 27017 --authenticationDatabase admin -d world -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
恢复 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
drop 表示恢复的时候把之前的集合 drop 掉(危险)
$ mongorestore -uroot -proot123 --port 27017 --authenticationDatabase admin -d oldboy --drop /mongodb/backup/oldboy
8.7 mongodump 和 mongorestore 高级企业应用(--oplog)
注意:这是 replica set 或者 master/slave 模式专用
--oplog use oplog for taking a point-in-time snapshot
8.7.1 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
use local
db.oplog.rs.find().pretty()
"ts" : Timestamp(1553597844, 1),
"op" : "n"
"o" :
"i": insert
"u": update
"d": delete
"c": db cmd
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)
8.7.2 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/backup
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
[mongod@db03 backup]$ cd /mongodb/backup/local/
[mongod@db03 local]$ ls
oplog.rs.bson oplog.rs.metadata.json
[mongod@db03 local]$ cp oplog.rs.bson ../oplog.bson
rm -rf /mongodb/backup/local/
mongorestore --port 38021 --oplogReplay --oplogLimit "1553659908:1" --drop /mongodb/backup/
8.9 分片集群的备份思路(了解)
-
你要备份什么?
- config server
- shard 节点
单独进行备份
-
备份有什么困难和问题
- chunk 迁移的问题:人为控制在备份的时候,避开迁移的时间窗口
- shard节点之间的数据不在同一时间点。选业务量较少的时候