应用场景

用户评论
游戏
问卷
日志
聊天信息
银行 金融流水

逻辑结构

Mongodb逻辑结构

MySQL逻辑结构

库database

集合(collection)

文档(document)

数据行

安装部署

1、系统准备

1)redhat或centos6.2以上系统
2)系统开发包完整
3)ip地址和hosts文件解析正常
4)iptables防火墙&SElinux关闭
5)关闭大页内存机制:

++++++++++++++++++++++++++++++++++++++
root用户下:
vim /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

#增加文件描述符
vim /etc/security/limit.conf
*   -   notify  65535                --------->末尾增加mowen

2、mongodb安装

创建所需用户和组

useradd mongod
passwd mongod

创建mongodb所需目录结构

mkdir -p /mongodb/{conf,log,data}

下载

https://www.mongodb.com/try/download/community

上传并解压软件到指定位置

[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

设置目录结构权限

chown -R mongod:mongod /mongodb

设置用户环境变量

su - mongod
vim .bash_profile
export PATH=/mongodb/bin:$PATH
source .bash_profile

启动mongodb(初始化)

mongod --dbpath=/mongodb/data --logpath=/mongodb/log/mongodb.log --port=27017 --logappend --fork

登录mongodb

[mongod@server2 ~]$ mongo
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
mongod -f /mongodb/conf/mongo.conf

mongodb的关闭方式

mongod -f mongo.conf  --shutdown

mongodb 使用systemd管理

[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

3、mongodb常用基本操作

3.0 mongodb 默认存在的库

> show databases;
admin   0.000GB
config  0.000GB
local   0.000GB

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

> use admin
> show tables
system.version
> show collections
system.version

admin库:系统预留库,MongoDB系统管理库
local库:本地预留库,存储关键日志
config库:MongoDB配置信息库

3.1 命令种类

# db 对象相关命令:
db.[TAB][TAB]
db.help()

# rs 复制集有关(replication set):
rs.[TAB][TAB]
rs.help()

# sh 分片集群(sharding cluster)
sh.[TAB][TAB]
sh.help()

4. mongodb对象操作

mongo

mysql

集合

文档

数据行

4.1 库的操作

> use test
> db.dropDatabase() 
{ "dropped" : "test", "ok" : 1 }

4.2 集合的操作

app> db.createCollection('a')
{ "ok" : 1 }
app> db.createCollection('b')

方法2:当插入一个文档的时候,一个集合就会自动创建。
use test
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})

4.3 文档操作

数据录入:
for(i=0;i<10000;i++){db.log.insert({"uid":i,"name":"mongodb","age":6,"date":new Date()})}

查询数据行数:
> db.log.count()

全表查询:
> db.log.find()

每页显示50条记录:
> help
> 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({})

查看集合存储信息
app> db.log.totalSize()   #集合中索引+数据压缩存储之后的大小

5. 用户及权限管理

5.1 验证库

验证库: 建立用户时use到的库,在使用用户时,要加上验证库才能登陆。
对于管理员用户,必须在admin下创建.

1. 建用户时,use到的库,就是此用户的验证库
2. 登录时,必须明确指定验证库才能登录
3. 通常,管理员用的验证库是admin,普通用户的验证库一般是所管理的库设置为验证库
4. 如果直接登录到数据库,不进行use,默认的验证库是test,不是我们生产建议的.
5. 从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 rundo -p 123 10.0.0.53/rundo

5.3 用户管理例子

# 创建超级管理员:管理所有数据库(必须use admin再去创建)
$ mongo
use admin
db.createUser(
{
    user: "root",
    pwd: "root123",
    roles: [ { role: "root", db: "admin" } ]
}
)

db.createUser({user:"admin",pwd:"root123",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})

# 验证用户:
> db.auth('root','root123')
1

# 配置文件中,加入以下配置
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')

查看用户:
use admin
db.system.users.find().pretty()

创建应用用户
use test
db.createUser(
{
user: "app01",
pwd: "app01",
roles: [ { role: "readWrite" , db: "test" } ]
}
)
mongo  -uapp01 -papp01 app

roles:指定用户的角色,可以用一个空数组给新用户设定空角色;在roles字段,可以指定内置角色和用户定义的角色。role里的角色可以选:

  Built-In Roles(内置角色):
    1. 数据库用户角色:read、readWrite;
    2. 数据库管理角色:dbAdmin、dbOwner、userAdmin;
    3. 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
    4. 备份恢复角色:backup、restore;
    5. 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase
    6. 超级用户角色:root 
    // 这里还有几个角色间接或直接提供了系统超级用户的访问(dbOwner 、userAdmin、userAdminAnyDatabase)
    7. 内部角色:__system

具体角色:

Read:允许用户读取指定数据库
readWrite:允许用户读写指定数据库
dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root:只在admin数据库中可用。超级账号,超级权限。

userAdminAnyDatabase 角色,用来管理用户,可以通过这个角色来创建、删除用户

5.4 删除用户(root身份登录,use到验证库)

删除用户
db.createUser(
{
user: "app02",
pwd: "app02",
roles: [ { role: "readWrite" , db: "test1" } ]
    
}
)

mongo -uroot -proot123 10.0.0.53/admin
use test1
db.dropUser("app02")

5.5 用户管理注意事项

1. 建用户要有验证库,管理员admin,普通用户是要管理的库
2. 登录时,注意验证
mongo -uapp01 -papp01 10.0.0.51:27017/test
3. 重点参数
net:
  port: 27017
  bindIp: 10.0.0.51,127.0.0.1
security:
  authorization: enabled

6. MongoDB复制集RS(ReplicationSet)

MongoDB快速入门_mongodb

MongoDB快速入门_数据库_02

6.1 基本原理

基本构成是1主2从的结构,自带互相监控投票机制(Raft)
如果发生主库宕机,复制集内部会进行投票选举,选择一个新的主库替代原有主库对外提供服务。同时复制集会自动通知客户端程序,
主库已经发生切换了。应用就会连接到新的主库。

6.2 Replication Set配置过程详解

6.2.1 规划

三个以上的mongodb节点(或多实例)

6.2.2 环境准备

多个端口:
28017、28018、28019、28020
多套目录:
su - mongod
mkdir -p /mongodb/28017/{conf,data,log}
mkdir -p /mongodb/28018/{conf,data,log}
mkdir -p /mongodb/28019/{conf,data,log}
mkdir -p /mongodb/28020/{conf,data,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.63,127.0.0.1
  port: 28017
replication:
  oplogSizeMB: 2048
  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

[mongod@mongodb ~]$ 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:28017         0.0.0.0:*               LISTEN      42772/mongod        
tcp        0      0 10.0.0.51:28017         0.0.0.0:*               LISTEN      42772/mongod        
tcp        0      0 127.0.0.1:28018         0.0.0.0:*               LISTEN      42802/mongod        
tcp        0      0 10.0.0.51:28018         0.0.0.0:*               LISTEN      42802/mongod        
tcp        0      0 127.0.0.1:28019         0.0.0.0:*               LISTEN      42831/mongod        
tcp        0      0 10.0.0.51:28019         0.0.0.0:*               LISTEN      42831/mongod        
tcp        0      0 127.0.0.1:28020         0.0.0.0:*               LISTEN      42861/mongod        
tcp        0      0 10.0.0.51:28020         0.0.0.0:*               LISTEN      42861/mongod        
unix  2      [ ACC ]     STREAM     LISTENING     94075    42861/mongod         /tmp/mongodb-28020.sock
unix  2      [ ACC ]     STREAM     LISTENING     94058    42831/mongod         /tmp/mongodb-28019.sock
unix  2      [ ACC ]     STREAM     LISTENING     94047    42802/mongod         /tmp/mongodb-28018.sock
unix  2      [ ACC ]     STREAM     LISTENING     94036    42772/mongod         /tmp/mongodb-28017.sock

6.3 配置普通复制集:

1主2从,从库普通从库
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'}]
          }           
rs.initiate(config)
{
	"ok" : 1,
	"operationTime" : Timestamp(1562603075, 1),
	"$clusterTime" : {
		"clusterTime" : Timestamp(1562603075, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	}
}

my_repl:SECONDARY> 
my_repl:SECONDARY> 
my_repl:PRIMARY> 
my_repl:PRIMARY> 

# 查询复制集状态
rs.status();

##初始化复制集的第一个服务器将会成为主复制集

6.4 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)

6.5 复制集管理操作

6.5.1 查看复制集状态

rs.status();    //查看整体复制集状态
rs.isMaster(); // 查看当前是否是主节点
rs.conf();  //查看复制集配置信息


STARTUP:刚加入到复制集中,配置还未加载
STARTUP2:配置已加载完,初始化状态
RECOVERING:正在恢复,不适用读
ARBITER: 仲裁者
DOWN:节点不可到达
UNKNOWN:未获取其他节点状态而不知是什么状态,一般发生在只有两个成员的架构,脑裂
REMOVED:移除复制集
ROLLBACK:数据回滚,在回滚结束时,转移到RECOVERING或SECONDARY状态
FATAL:出错。查看日志grep “replSet FATAL”找出错原因,重新做同步
PRIMARY:主节点
SECONDARY:备份节点

6.5.2 添加删除节点

rs.remove("ip:port"); // 删除一个节点
rs.add("ip:port");    // 新增从节点
rs.addArb("ip:port"); // 新增仲裁节点

# 例子:
添加 arbiter节点
1、连接到主节点
[mongod@db03 ~]$ mongo --port 28018 admin
2、添加仲裁节点
my_repl:PRIMARY> rs.addArb("10.0.0.53:28020")
3、查看节点状态
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()

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)   

取消以上配置:
cfg=rs.conf()
cfg.members[2].priority=1
cfg.members[2].hidden=false
cfg.members[2].slaveDelay=0
rs.reconfig(cfg)   

#说明:members[]的数值是rs.conf从上到下数的,并不一定是"_id"的值
配置成功后,通过以下命令查询配置后的属性:

rs.conf();

MongoDB快速入门_mongodb_03

6.5.4 副本集其他操作命令

查看副本集的配置信息
admin> rs.conf()
查看副本集各成员的状态
admin> rs.status()

##副本集角色切换(不要人为随便操作):
admin> rs.stepDown()     ##按照id号轮询,有一定延时

注:
admin> rs.freeze(300) //锁定从,使其不会转变成主库
freeze()和stepDown单位都是秒。

设置副本节点可读:在副本节点执行
admin> rs.slaveOk()

例子:
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

6.5.5 副本集数据同步原理

一个健康的secondary在运行时,会选择一个离自己最近的,数据比自己新的节点进行数据同步。选定节点后,它会从这个节点拉取oplog同步日志,具体流程:
       1.执行这个op日志
       2.将这个op日志写入到自己的oplog中(local.oplog.rs)
       3.再请求下一个op日志

如果同步操作在第1步和第2步之间出现问题宕机,那么secondary再重新恢复后,会检查自己这边最新的oplog,由于第2步还没有执行,所以自己这边还没有这条写操作的日志。这时候他会再把刚才执行过的那个操作执行一次。那对同一个写操作执行两次会不会有问题呢? 

MongoDB所有的oplog都是可以重复执行的,比如你执行 {$inc:{counter:1}} 对counter字段加1,counter字段在加1 后值为2,那么在oplog里并不会记录 {$inc:{counter:1}} 这个操作,而是记录 {$set:{counter:2}}这个操作。所以无论多少次执行同一个写操作,都不会出现问题。

注:从节点不一定要从主节点的操作日志来读取数据,它也可以选择距离自己最近的(根据ping的时间来计算)的且比自己操作日志记录更新的从节点获取操作日志。

6.5.6 副本集手动指定同步源

#从节点运行:
db.adminCommand( { replSetSyncFrom: "hostname<:port>" } );
rs.syncFrom("hostname<:port>");
#注明:3.4版本之后再初始化同步阶段运行这个命令会停止初始化同步开始指向新目标源,之前的版本需要在初始化同步之后才生效次操作。

6.5.7 mongodb链式复制

C        B        A
           <====>
  <====>   <---->

B和A之间有两条通道,双线那条是真正的同步连接,单线那条是一个虚拟连接。
注意:MongoDB这种链式同步结构类似于Hadoop中HDFS中数据块的流式复制,这样的好处是可以大大减轻主节点的压力,提高数据同步的速度。

7. MongoDB Sharding Cluster 分片集群

MongoDB快速入门_复制集_04

7.1 规划

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

7.2 Shard节点配置过程

7.2.1 目录创建:

mkdir -p /mongodb/38021/{conf,log,data}
mkdir -p /mongodb/38022/{conf,log,data}
mkdir -p /mongodb/38023/{conf,log,data}
mkdir -p /mongodb/38024/{conf,log,data}
mkdir -p /mongodb/38025/{conf,log,data}
mkdir -p /mongodb/38026/{conf,log,data}

7.2.2 修改配置文件:

第一组复制集搭建: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.51,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.51,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 
ps -ef |grep mongod

mongo --port 38021
use  admin
config = {_id: 'sh1', members: [
                          {_id: 0, host: '10.0.0.51:38021'},
                          {_id: 1, host: '10.0.0.51:38022'},
                          {_id: 2, host: '10.0.0.51:38023',"arbiterOnly":true}]
          }

rs.initiate(config)


mongo --port 38024
use admin
config = {_id: 'sh2', members: [
                          {_id: 0, host: '10.0.0.51:38024'},
                          {_id: 1, host: '10.0.0.51:38025'},
                          {_id: 2, host: '10.0.0.51:38026',"arbiterOnly":true}]
          }

rs.initiate(config)

7.3 config server节点配置

7.3.1 目录创建

mkdir -p /mongodb/38018/{conf,log,data}
mkdir -p /mongodb/38019/{conf,log,data}
mkdir -p /mongodb/38020/{conf,log,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: 10.0.0.51,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
use  admin
config = {_id: 'configReplSet', members: [
                          {_id: 0, host: '10.0.0.51:38018'},
                          {_id: 1, host: '10.0.0.51:38019'},
                          {_id: 2, host: '10.0.0.51:38020'}]
          }

rs.initiate(config) 

注:configserver 可以是一个节点,官方建议为复制集(新版本中,要求必须是复制集)。configserver不能有arbiter。

注:mongodb 3.4之后,虽然要求config server为replica set,但是不支持arbiter

7.4 mongos节点配置

7.4.1创建目录:

mkdir -p /mongodb/38017/{conf,log}

7.4.2配置文件:

cat > /mongodb/38017/conf/mongos.conf <<EOF
systemLog:
  destination: file
  path: /mongodb/38017/log/mongos.log
  logAppend: true
net:
  bindIp: 10.0.0.51,127.0.0.1
  port: 38017
sharding:
  configDB: configReplSet/10.0.0.51:38018,10.0.0.51:38019,10.0.0.51:38020
processManagement:
  fork: true
EOF

7.4.3启动mongos

mongos -f /mongodb/38017/conf/mongos.conf

7.5 分片集群添加节点

连接到其中一个mongos(10.0.0.51),做以下配置

(1)连接到mongs的admin数据库
# su - mongod
$ mongo 10.0.0.51:38017/admin

(2)添加分片
db.runCommand( { addshard : "sh1/10.0.0.51:38021,10.0.0.51:38022,10.0.0.51:38023",name:"shard1"} )

db.runCommand( { addshard : "sh2/10.0.0.51:38024,10.0.0.51:38025,10.0.0.51:38026",name:"shard2"} )

(3)列出分片
mongos> db.runCommand( { listshards : 1 } )

(4)整体状态查看

mongos> sh.status();

7.6 使用分片集群

  • 默认chunk 64M

7.6.1 RANGE分片配置及测试

1、激活数据库分片功能
mongo --port 38017 admin
admin>  ( { enablesharding : "数据库名称" } )
例子:
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.6.2 Hash分片例子

对rundo库下的vast大表进行hash

创建哈希索引

(1)对于rundo开启分片功能
mongo --port 38017 admin
use admin
admin> db.runCommand( { enablesharding : "rundo" } )
(2)对于rundo库下的vast表建立hash索引
use rundo
rundo> db.vast.ensureIndex( { id: "hashed" } )
(3)开启分片
use admin
admin > sh.shardCollection( "rundo.vast", { id: "hashed" } )
(4)录入10w行数据测试
use rundo
for(i=1;i<100000;i++){ db.vast.insert({"id":i,"name":"shenzheng","age":70,"date":new Date()}); }
(5)hash分片结果测试
mongo --port 38021
use rundo
db.vast.count();

mongo --port 38024
use rundo
db.vast.count();

7.7 分片集群的查询及管理

7.7.1 判断是否Shard集群

admin> db.runCommand({ isdbgrid : 1})

7.7.2 列出所有分片信息

admin> db.runCommand({ listshards : 1})

7.7.3 列出开启分片的数据库

admin> use config
config> db.databases.find( { "partitioned": true } )

或者:

config> db.databases.find() //列出所有数据库分片情况

7.7.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.7.5 查看分片的详细信息

admin> sh.status()

7.7.6 删除分片节点(谨慎)

(1)确认blance是否在工作

sh.getBalancerState()

(2)删除shard2节点(谨慎)

mongos> db.runCommand( { removeShard: "shard2" } )

注意:删除操作一定会立即触发blancer。

7.8 balancer操作

7.8.1 介绍

mongos的一个重要功能,自动巡查所有shard节点上的chunk的情况,自动做chunk迁移。

什么时候工作?

1、自动运行,会检测系统不繁忙的时候做迁移

2、在做节点删除的时候,立即开始迁移工作

3、balancer只能在预设定的时间窗口内运行

有需要时可以关闭和开启blancer(备份的时候)

mongos> sh.stopBalancer()

mongos> sh.startBalancer()

7.8.2 自定义自动平衡进行的时间段

https://docs.mongodb.com/manual/tutorial/manage-sharded-cluster-balancer/#schedule-the-balancing-window

#连接到config
use config
sh.setBalancerState( true )

db.settings.update({ _id : "balancer" }, { $set : { "activeWindow" : { "start" : "12:00", "stop" : "23:00" } } }, true )

sh.getBalancerWindow()

sh.status()

删除:
 db.settings.update({ "_id" : "balancer" }, { $unset : { activeWindow : 1 }});
  • 关闭某个集合的balance:
sh.disableBalancing("students.grades")

打开某个集合的balancer

sh.enableBalancing("students.grades")

确定某个集合的balance是开启或者关闭

db.getSiblingDB("config").collections.findOne({_id : "students.grades"}).noBalance;

8. 备份恢复

8.1 备份恢复工具介绍:

(1)mongoexport/mongoimport

(2)mongodump/mongorestore

8.2 备份工具区别在哪里?

mongoexport/mongoimport备份导出:json csv
应用场景:
1、异构平台迁移  mysql  <---> mongodb
2、同平台,跨大版本:mongodb 2  ----> mongodb 3

mongodump/mongorestore 日常备份恢复时使用.

8.3 导出工具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 rundo -c log -o /mongodb/log.json

注:备份文件的名字可以自定义,默认导出了JSON格式的数据。
  1. 单表备份至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>  number of insert operations to run concurrently                                                  (defaults to 1)

8.4.1 数据恢复:

  • 1.恢复json格式表数据到log1
mongoimport -uroot -proot123 --port 27017 --authenticationDatabase admin -d rundo -c log1 /mongodb/log.json

2.恢复csv格式的文件到log2

上面演示的是导入JSON格式的文件中的内容,如果要导入CSV格式文件中的内容,则需要通过--type参数指定导入格式,具体如下所示:

注意:
(1)csv格式的文件头行,有列名字
mongoimport  -uroot -proot123 --port 27017 --authenticationDatabase admin  -d rundo -c log2 --type=csv --headerline --file  /mongodb/log.csv

(2)csv格式的文件头行,没有列名字
mongoimport  -uroot -proot123 --port 27017 --authenticationDatabase admin  -d rundo -c log3 --type=csv -f id,name,age,date --file  /mongodb/log.csv

--headerline:指明第一行是列名,不需要导入。

8.5 迁移

mysql  -----> mongodb 

world数据库下city表进行导出,导入到mongodb
(1)mysql开启安全路径:

vim /etc/my.cnf  --->添加以下配置

secure-file-priv=/tmp

重启数据库生效:

/etc/init.d/mysqld restart

(2)导出mysql的city表数据

select * from world.city into outfile '/tmp/city1.csv' fields 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 --file  /tmp/city1.csv

use world

db.city.find({CountryCode:"CHN"});
+++++++++++++++++++++++++++++++++++++

world共100张表,全部迁移到mongodb

提示:使用infomation_schema.columns + information_schema.tables

1. select table_name ,group_concat(column_name) from columns where table_schema='world' group by table_name;

2. select * from world.city into outfile '/tmp/world_city.csv' fields terminated by ',';
3. 语法:
导出:
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';

导入csv:
mysql -uroot -p

load data infile '/tmp/test.csv' into table test_info fields terminated by ',' optionally enclosed by '"' escaped by '"'  lines terminated by '\r\n';

select * from test_info into outfile '/tmp/test.csv' 

#c参数说明:
fields terminated by ','    字段间以,号分隔
optionally enclosed by '"'   字段用"号括起
escaped by '"'           字段中使用的转义符为"
lines terminated by '\r\n';  行以\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基本使用

全库备份:
mkdir /mongodb/backup

$ mongodump  -uroot -proot123 --port 27017 --authenticationDatabase admin -o /mongodb/backup
备份单一world库:
$ mongodump  -uroot -proot123 --port 27017 --authenticationDatabase admin -d world -o /mongodb/backup/
备份rundo库下的log集合(所有表)
$ mongodump  -uroot -proot123 --port 27017 --authenticationDatabase admin -d rundo -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  -uroot -proot123 --port 27017 --authenticationDatabase admin -d world1  /mongodb/backup/world

恢复word库下的t1集合

[mongod@db03 rundo]$ mongorestore  -uroot -proot123 --port 27017 --authenticationDatabase admin -d world -c t1  --gzip  /mongodb/backup.bak/rundo/log1.bson.gz

drop表示恢复的时候把之前的集合删除掉(危险)

$ mongorestore  -uroot -proot123 --port 27017 --authenticationDatabase admin -d rundo --drop  /mongodb/backup/rundo

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),wiretiger引擎它的默认大小是free磁盘空间的5%;(可以通过--oplogSizeMB参数修改).位于local库的db.oplog.rs。

Storage Engine| Default Oplog Size| Lower Bound |Upper Bound
---|---|---
In-Memory Storage Engine |5% of physical memory |50 MB| 50 GB
WiredTiger Storage Engine |5% of free disk space |990 MB| 50 GB

db.oplog.rs中记录的是整个mongod实例一段时间内数据库的所有变更(插入/更新/删除)操作.
当空间用完时新记录自动覆盖最老的记录.

其覆盖范围被称作oplog时间窗口。需要注意的是,因为oplog是一个定容集合,所以时间窗口能覆盖的范围会因为你单位时间内的更新次数不同而变化.

查看当前的oplog时间窗口预计值:

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企业级应用

(1)实现热备,在备份时使用--oplog选项

注:在备份过程,模拟数据插入

(2)准备测试数据:
[mongod@db01 conf]$ mongo --port 28018
use rundo
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 --oplogReplay /mongodb/backup

8.8 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 分片集群的备份思路(了解)

8.9.1 要备份什么?

config server
shard 节点
单独进行备份

8.9.2 备份有什么困难和问题?

1)chunk迁移的问题
人为控制在备份的时候,避开迁移的时间窗口

2)shard节点之间的数据不在同一时间点。
选业务量较少的时候
Ops Manager

#MongoDB Master/Slave主从复制

主从复制MongoDB中比较常用的一种方式,如果要实现主从复制至少应该有两个MongoDB实例,一个作为主节点负责客户端请求,另一个作为从节点负责从主节点映射数据,提供数据备份,客户端读取等,推荐一主多从模式

##MongoDB主从复制的实现方式:

主节点的操作会被记录为oplog,存储在系统数据库local的集合oplog.$main中,这个集合中的每个文档都代表主节点的一个操作(不包括查询)
从节点定期从主服务器获取oplog数据,并在本机进行执行
oplog使用的是固定集合,随着操作的逐渐增加,新的文档会逐渐覆盖旧的文档

##MongoDB使用注意点或缺点:

每个从节点必须知晓其对应的主节点地址
只允许主节点进行数据更新操作
主节点宕机服务不可用
3.2版本以后已经移除

##Mongodb主从复制配置项详解:

master:默认为false,当设置为true,则配置当前实例作为主节点。
slave:默认为false,当设置为true,则配置当前实例作为从节点。
source:默认为空,用于从节点,指定从节点的复制来源(主节点的IP+端口),格式为:<host><:port>
only:默认为空,用于从节点,主动复制,默认复制主节点上所有的数据库,通过设置此项指定需要复制的数据库名称
slavedelay:设置从库同步主库的延迟时间,用于从设置,默认为0,单位秒。
autoresync:默认为false,用于从设置。是否自动重新同步。设置为true,如果落后主超过10秒,会强制从自动重新同步。如果oplogSize太小,此设置可能有问题。如果OPLOG大小不足以存储主的变化状态和从的状态变化之间的差异,这种情况下强制重新同步是不必要的。当设置autoresync选项设置为false,10分钟内从不会进行大于1次的自动重新同步。

##主从配置实例(一主一从)

主节点 
/usr/local/mongodb/bin/mongod --fork --port 40000 --master --dbpath /u01/mongodata/db/geoslave/ --logpath /u01/mongodata/log/geomaster.log --logappend

从节点配置
 /usr/local/mongodb/bin/mongod --fork --slave --port 40000 --dbpath /u01/mongodata/db/geoslave/ --logpath /u01/mongodata/log/geosalve.log --logappend --nojournal  --source maseter:40000


在主库上创建数据库 masterslavetest 并创建一些测试数据

use masterslavetest

for (i = 5000; i < 100000; i++) {

db.users.insert({

"i": i,

"userName": "user" + i,

"age": Math.floor(Math.random() * 120),

"created": new Date(),

total: Math.floor(Math.random() * 100) * i

})

}

在两个实例上分别执行 以下命令 可以看到在两个数据库上的数据保持一致,这时在主数据库上执行CRUD等操作时,从库数据依然与主库一致

db.users.find({})

##两条指令

db.printReplicationInfo(): //查看主节点的信息
db.printSlaveReplicationInfo(): //查看从节点的信息