MongoDB入门

Nosql分布式数据库-MongoDB

MongoDB提供高性能的数据持久性。特别是,

  • 对嵌入式数据模型的支持减少了数据库系统上的I / O活动。
  • 索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键。

安装mongodb

官网下载地址:https://www.mongodb.com/try/download

下载3.6.12版本:

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.6.12.tgz

逻辑结构

Mongodb逻辑结构 MySQL逻辑结构
库database
集合(collection)
文档(document) 数据行

系统准备

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

(5)为什么要关闭

Transparent Huge Pages (THP) 是一种Linux内存管理系统,可通过使用较大的内存页面来减少具有大量内存的计算机上的翻译后备缓冲区(TLB)查找的开销。 具有稀疏而不是连续的内存访问模式。 您应该在Linux机器上禁用THP,以确保MongoDB的最佳性能。

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


或者临时关闭
echo never > /sys/kernel/mm/transparent_hugepage/enabled		
echo never > /sys/kernel/mm/transparent_hugepage/defrag

mongodb安装

创建mongod用户

useradd mongod
passwd mongod

创建目录结构

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

解压软件到指定位置

tar xf mongodb-linux-x86_64-rhel70-3.6.12.tgz -C /mongodb
cp -a /mongodb/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

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

有警告就对应处理一下
比如vim /etc/security/limits.conf 
#*       -       nofile       65535 

登录mongodb

$ mongo		默认连接本机test数据库

配置文件启动mongodb

$vim /mongodb/conf/mongodb.conf

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

yaml模式

--系统日志有关  
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>                       -- 监听地址,如果不配置这行是监听在0.0.0.0
   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.9.119.18,127.0.0.1
EOF

启动

$mongod -f /mongodb/conf/mongodb.conf

关闭

mongod -f /mongodb/conf/mongodb.conf --shutdown

systemd管理mongodb

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

启动关闭

systemctl start mongod
systemctl stop mongod
systemctl restart mongod

基本操作

默认存在的库

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

数据库对象(库(database),表(collection),行(document))

DB级别命令

db            显示当前数据库
db.getName()  显示当前数据库
db.[TAB]  类似于linux中的tab功能补全
db.help() db级别的命令使用帮助

db.version() 查看当前db版本
db.stats()	显示当前数据库状态
db.getMongo()	查看当前数据库的连接机器地址

collection级别

db.Collection_name.xxx  xxx操作
db.xyz.drop()

document级别

db.t1.insert()

复制集有关(replication set)

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

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

freeze()和stepDown单位都是秒。
rs.stepDown()	//副本集角色切换(不要人为随便操作)
rs.freeze(300)	//锁定从,使其不会转变成主库
rs.slaveOk()	//设置副本节点可读:在副本节点执行

>rs.printSlaveReplicationInfo()	//查看副本节点(监控主从延时)
source: 10.9.119.18:28018
        syncedTo: Sat Apr 17 2021 13:28:11 GMT+0800 (CST)
        0 secs (0 hrs) behind the primary 
source: 10.9.119.18:28019
        syncedTo: Sat Apr 17 2021 13:28:11 GMT+0800 (CST)
        0 secs (0 hrs) behind the primary 
        

分片集群(sharding cluster)

sh.status();  分片集群整体状态查看

use admin
db.runCommand({ isdbgrid : 1})	判断是否Shard集群
db.runCommand({ listshards : 1})	列出所有分片信息
db.printShardingStatus()	查看分片的详细信息

列出开启分片的数据库
use config
db.databases.find( { "partitioned": true } ) 或者 db.databases.find() //列出所有数据库分片情况
db.collections.find().pretty()	查看分片的片键

删除分片节点(谨慎)
sh.getBalancerState()	确认blance是否在工作
db.runCommand( { removeShard: "shard2" } )	删除shard2节点(谨慎)
删除操作一定会立即触发blancer!!!

库的操作

use local 创建数据库:当use的时候,系统就会自动创建一个数据库。如果use之后没有创建任何集合,系统就会删除这个数据库。
db.dropDatabase() 删除数据库

集合的操作

方法一:创建集合

> use app
switched to db app
> db.createCollection('a')  创建集合
{ "ok" : 1 }
> db.createCollection('b')	创建集合
{ "ok" : 1 }
> show collections	查看库当前集合
a
b
> db.getCollectionNames()	查看库当前集合
[ "a", "b" ]

方法二:当插入一个文档的时候,一个集合就会自动创建

> use app1
switched to db app1
> db.app1.insert({id : "18" ,name : "ruan" ,age : "23" ,gender : "female",address : "sz"})
WriteResult({ "nInserted" : 1 })
> show collections
app1

查询数据

> db.app1.find({id:"18"}) // 方法一
{ "_id" : ObjectId("6079a63eae399e884cc18352"), "id" : "18", "name" : "ruan", "age" : "23", "gender" : "female", "address" : "sz" }
> db.app1.find({id:"18"}).pretty() // 方法二
{
        "_id" : ObjectId("6079a63eae399e884cc18352"),
        "id" : "18",
        "name" : "ruan",
        "age" : "23",
        "gender" : "female",
        "address" : "sz"
}

删除集合

> db.app1.drop()
true
> show collections
app
app2

重命名集合

> show collections
app
app2
> db.app2.renameCollection("app1") // 重命名
{ "ok" : 1 }
> show collections
app
app1

文档的操作

批量插入数据

for(i=0;i<10000;i++){db.app.insert({"uid":i,"name":"ruan","age":23,"date":new Date()})}

查询集合中的记录数

db.app.find()	// 默认每页显示20条记录,当显示不下的的情况下,可以用it迭代命令查询下一页数据。

设置每页显示数据的大小:
> DBQuery.shellBatchSize=50 //每页显示50条记录

> db.app.findOne() //查看第1条记录
> db.app.count() //查询总的记录数

删除集合中的记录数

db.app.distinct("name") //查询去掉当前集合中某列的重复数据,去重
db.app.remove({}) //删除集合中所有记录

查看集合存储信息

db.app.stats()	//详细信息
db.app.dataSize() //集合中数据的原始大小
db.app.totalIndexSize() //集合中索引数据的原始大小
db.app.totalSize() //集合中索引+数据压缩存储之后的大小 kb大小值
db.app.storageSize() //集合中数据压缩存储的大小

帮助

help
KEYWORDS.help()
KEYWORDS.[TAB]

show 
use 
db.help()
db.a.help()
rs.help()
sh.help()

常用的命令

show dbs	查询所有数据库
show  tables	查看所有的collection
use local 	切换数据库

用户管理

验证库是建立用户时use到的库(db 查看),在使用用户时,要加上验证库才能登陆
对于管理员用户,必须在admin下创建

步骤:

1. 建用户时,use到的库,就是此用户的验证库
2. 登录时,必须明确指定验证库才能登录
3. 通常,管理员用的验证库是admin,普通用户的验证库一般是所管理的库设置为验证库
4. 如果直接登录到数据库,不进行use,默认的验证库是test,生产不建议使用test库

查看用户

use admin
db.system.users.find().pretty()

删除用户

use app
db.dropUser("app02")

创建语法

db.createUser
{
    user: "<name>",
    pwd: "<cleartext password>",
    roles: [
       { role: "<role>",
     db: "<database>" } | "<role>",
    ...
    ]
}


基本语法说明:
	user:用户名
	pwd:密码
roles:
    role:角色名 //role:root(超级管理员),dbAdmin(库管理员),readWrite(读写),read(只读)
    db:作用对象(库)
   

用户管理例子

一、创建超级管理员

必须use admin再去创建

use admin

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

验证用户
db.auth('root','admin')

配置文件中,加入以下配置

security:
  authorization: enabled

重启mongodb

mongod -f /mongodb/conf/mongo.conf --shutdown 
mongod -f /mongodb/conf/mongo.conf 

登录验证

mongo -uroot -padmin  admin
或者
mongo -uroot -padmin  10.9.119.18/admin
或者
mongo
use admin
db.auth('root','admin')

二、创建库管理用户

use app

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

认证
> db.auth('app','admin')
1
登录测试
mongo -uapp -padmin app

三、创建对app数据库,读、写权限的用户

use app

db.createUser(
	{
        user: "app01",
        pwd: "app01",
        roles: [ { role: "readWrite", db: "app" } ]
	}
)

认证
> db.auth('app01','app01')
1

登录测试
mongo  -uapp01 -papp01 app

四、创建对app数据库读写权限的用户并对test数据库具有读权限

use app

db.createUser(
	{
        user: "app02",
        pwd: "app02",
        roles: [ { role: "readWrite", db: "app" },
        	{ role: "read", db: "test" }
        	]
	}
)

认证
> db.auth('app02','app02')
1

登录测试
mongo  -uapp02 -papp02 app

复制集

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

配置Replication Set

资源有限单台配置多实例

多套目录
su - mongod 
mkdir -p /mongodb/{28017,28018,28019,28020}/{conf,data,log,bin}

配置文件

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.9.119.18,127.0.0.1
  port: 28017
replication: # 复制集相关的配置
  oplogSizeMB: 2048 # 和二进制相关的日志,这里设置两个G
  replSetName: my_repl # 复制集的名
EOF

cp /mongodb/28017/conf/mongod.conf /mongodb/28018/conf/mongod.conf
cp /mongodb/28017/conf/mongod.conf /mongodb/28019/conf/mongod.conf
cp /mongodb/28017/conf/mongod.conf /mongodb/28020/conf/mongod.conf
sed -i 's#28017#28018#g' /mongodb/28018/conf/mongod.conf 
sed -i 's#28017#28019#g' /mongodb/28019/conf/mongod.conf
sed -i 's#28017#28020#g' /mongodb/28020/conf/mongod.conf

启动多个实例

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 -f /mongodb/28017/conf/mongod.conf --shutdown
mongod -f /mongodb/28018/conf/mongod.conf --shutdown
mongod -f /mongodb/28019/conf/mongod.conf --shutdown
mongod -f /mongodb/28020/conf/mongod.conf --shutdown

查看4个端口是否启动成功

netstat -lnp|grep 280

配置普通复制集

1主2从

mongo --port 28017 admin
// _id和配置文件的replication.replSetName保持一致
config = {_id: 'my_repl', members: [
                          {_id: 0, host: '10.9.119.18:28017'},
                          {_id: 1, host: '10.9.119.18:28018'},
                          {_id: 2, host: '10.9.119.18:28019'}]
}

初始化
rs.initiate(config) 

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

配置1主1从1个arbiter

arbiter节点:主要负责选主过程中的投票,但是不存储任何数据,也不提供任何服务

mongo --port 28017 admin
config = {_id: 'my_repl', members: [
                          {_id: 0, host: '10.9.119.18:28017'},
                          {_id: 1, host: '10.9.119.18:28018'},
                          {_id: 2, host: '10.9.119.18:28019',"arbiterOnly":true}]
          }    
		  
rs.initiate(config) 

rs.status();

添加arbiter节点

连接到主节点
>rs.status(); 查看哪个是主节点"stateStr" : "PRIMARY"
mongo --port 28017 admin

添加仲裁节点
>rs.addArb("10.9.119.18:28020")

查看节点状态
>rs.isMaster()

        "hosts" : [
                "10.9.119.18:28017",
                "10.9.119.18:28018",
                "10.9.119.18:28019"
        ],
        "arbiters" : [
                "10.9.119.18:28020"
        ],
        

删除节点和新增节点

rs.remove("10.9.119.18:28018"); // 删除一个节点
rs.isMaster() // 查看节点状态
rs.add("10.9.119.18:28018")// 新增从节点
rs.isMaster() // 查看节点状态

特殊从节点

介绍:
arbiter节点:主要负责选主过程中的投票,但是不存储任何数据,也不提供任何服务
hidden节点:隐藏节点,不参与选主,也不对外提供服务。
delay节点:延时节点,数据落后于主库一段时间,因为数据是延时的,也不应该提供服务或参与选主,所以通常会配合hidden(隐藏)
一般情况下会将delay+hidden一起配置使用

配置延时节点(一般延时节点也配置成hidden)

cfg=rs.conf() 
cfg.members[2].priority=0 //这个[2]是什么意思,从rs.conf()的"members"开始数(从0开始)
cfg.members[2].hidden=true
cfg.members[2].slaveDelay=120 // 延时从库
rs.reconfig(cfg)    

>rs.conf(); 如以下的"_id" : 3 就是[2]
{
        "_id" : "my_repl",
        "version" : 4,
        "protocolVersion" : NumberLong(1),
        "members" : [
        		{
                        "_id" : 0,
                        "host" : "10.9.119.18:28017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 1,
                        "host" : "10.9.119.18:28018",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 3,
                        "host" : "10.9.119.18:28020",
                        "arbiterOnly" : true,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 0,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
 ...
配置延时节点前
                {
                        "_id" : 3,
                        "host" : "10.9.119.18:28020",
                        "arbiterOnly" : true,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 0,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
-----------------------------------------------------------------
配置延时节点后
				{
                        "_id" : 3,
                        "host" : "10.9.119.18:28020",
                        "arbiterOnly" : true,
                        "buildIndexes" : true,
                        "hidden" : true,
                        "priority" : 0,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(120),
                        "votes" : 1
                },

取消延时节点配置

cfg=rs.conf() 
cfg.members[2].priority=1
cfg.members[2].hidden=false
cfg.members[2].slaveDelay=0
rs.reconfig(cfg)  
rs.conf()查看取消配置后
                {
                        "_id" : 3,
                        "host" : "10.9.119.18:28020",
                        "arbiterOnly" : true,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 0,
                        "tags" : {

                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },

分片集群

MongoDB Sharding Cluster 分片集群

分片是一种用于在多台计算机之间分配数据的方法。MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署。

具有大数据集或高吞吐量应用程序的数据库系统可能会挑战单个服务器的容量。例如,高查询率可能会耗尽服务器的CPU容量。大于系统RAM的工作集大小会增加磁盘驱动器的I / O容量。

解决系统增长的方法有两种:垂直缩放和水平缩放。

垂直扩展涉及增加单个服务器的容量,例如使用功能更强大的CPU,添加更多RAM或增加存储空间量。可用技术的局限性可能会限制一台计算机对于给定的工作负载没有足够的功能。此外,基于云的提供程序具有基于可用硬件配置的严格上限。结果,对于垂直缩放有实际的最大值。

水平扩展涉及划分系统数据集并在多台服务器上加载,并添加其他服务器以根据需要增加容量。虽然单台计算机的整体速度或容量可能不高,但是每台计算机只能处理全部工作量的一部分,因此与单台高速大容量服务器相比,可能会提供更高的效率。扩展部署的容量仅需要根据需要添加其他服务器,这可以比单台机器的高端硬件降低总体成本。折衷方案是增加基础结构和部署维护的复杂性。

MongoDB通过分片(sharding)支持水平扩展

MongoDB分片集群由以下组件组成:

  • shard:每个碎片包含碎片数据的子集。每个分片都可以部署为[副本集(replica-set)。
  • mongos:mongos充当查询路由器,在客户端应用程序和分片群集之间提供接口。
  • config-servers:配置服务器存储集群的元数据和配置设置。从MongoDB 3.4开始,配置服务器必须部署为副本集(CSRS)

分片集群中组件的交互:

分片集群组件交互

配置分片集群

规划

10个实例:38017-38026
	mongos:38017
	config-servers:3台构成的复制集(1主两从,不支持arbiter)38018-38020(复制集名字configsvr)
	shard节点:
		sh1:38021-28023    (1主两从,其中一个节点为arbiter,复制集名字sh1)
		sh2:38024-38026    (1主两从,其中一个节点为arbiter,复制集名字sh2) 

shard复制集配置

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

配置文件
---------------------------sh1---------------------------
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: 0.0.0.0
  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 -i 's#38021#38022#g' /mongodb/38022/conf/mongodb.conf 
sed -i 's#38021#38023#g' /mongodb/38023/conf/mongodb.conf 

---------------------------sh2---------------------------
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: 0.0.0.0
  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 -i 's#38024#38025#g' /mongodb/38025/conf/mongodb.conf 
sed -i 's#38024#38026#g' /mongodb/38026/conf/mongodb.conf 

启动所有节点
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 

搭建复制集
---------------------------sh1---------------------------
mongo --port 38021 admin

config = {_id: 'sh1', members: [
                          {_id: 0, host: '10.9.119.18:38021'},
                          {_id: 1, host: '10.9.119.18:38022'},
                          {_id: 2, host: '10.9.119.18:38023',"arbiterOnly":true}]
           }

rs.initiate(config)
---------------------------sh2---------------------------
mongo --port 38024  admin

config = {_id: 'sh2', members: [
                          {_id: 0, host: '10.9.119.18:38024'},
                          {_id: 1, host: '10.9.119.18:38025'},
                          {_id: 2, host: '10.9.119.18:38026',"arbiterOnly":true}]
           }
  
rs.initiate(config)

config-servers节点配置

config-servers可以是一个节点,官方建议复制集。config-servers不能有arbiter。
mongodb 3.4之后,虽然要求config-servers为replica set,但是不支持arbiter

创建目录
mkdir -p /mongodb/{38018,38019,38020}/{conf,data,log}

配置文件
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: 0.0.0.0
  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 -i 's#38018#38019#g' /mongodb/38019/conf/mongodb.conf 
sed -i 's#38018#38020#g' /mongodb/38020/conf/mongodb.conf

启动所有节点
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.9.119.18:38018'},
                          {_id: 1, host: '10.9.119.18:38019'},
                          {_id: 2, host: '10.9.119.18:38020'}]
           }
rs.initiate(config)  

mongos节点配置

创建目录
mkdir -p /mongodb/38017/{conf,log}

配置文件
cat >/mongodb/38017/conf/mongos.conf<<EOF
systemLog:
  destination: file
  path: /mongodb/38017/log/mongos.log
  logAppend: true
net:
  bindIp: 0.0.0.0
  port: 38017
sharding:
  configDB: configReplSet/10.9.119.18:38018,10.9.119.18:38019,10.9.119.18:38020
processManagement: 
  fork: true
EOF

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

连接到其中一个mongos的admin库
mongo --port 38017 admin

添加分片
db.runCommand( { addshard : "sh1/10.9.119.18:38021,10.9.119.18:38022,10.9.119.18:38023",name:"shard1"} )
db.runCommand( { addshard : "sh2/10.9.119.18:38024,10.9.119.18:38025,10.9.119.18:38026",name:"shard2"} )

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

分片集群整体状态查看
sh.status();

分片策略

RANGE分片配置及测试

Ranged根据分片键值将数据划分为多个范围。然后,根据分片键值为每个分配一个范围

test库下的vast大表进行手工分片

激活数据库分片功能
mongo --port 38017 admin

db.runCommand( { enablesharding : "test" } )	// ( { enablesharding : "数据库名称" } )

指定分片建对集合分片,创建索引
use test
>db.vast.ensureIndex( { id: 1 } )

开启分片
use admin
>db.runCommand( { shardcollection : "test.vast",key : {id: 1} } )

集合分片验证
use test
>for(i=1;i<1000000;i++){ db.vast.insert({"id":i,"name":"ruan","age":23,"date":new Date()}); }
>db.vast.stats()

分片结果测试
连接sh1
mongo --port 38021
db.vast.count();

连接sh2
mongo --port 38024
db.vast.count();

哈希分片

哈希分片涉及计算分片键字段值的哈希值。然后,根据散列的分片键值为每个分配一个范围。

注意:使用哈希索引解析查询时,MongoDB自动计算哈希值。应用程序也不会需要计算哈希值。

对app库下的vast大表进行hash

连接到其中一个mongos
mongo --port 38017 admin

开启数据库分片功能
db.runCommand( { enablesharding : "app" } )

对app库下的vast表建立hash索引
use app
db.vast.ensureIndex( { id: "hashed" } )

开启分片
use admin
sh.shardCollection( "app.vast", { id: "hashed" } )

集合分片验证
use app
for(i=1;i<100000;i++){ db.vast.insert({"id":i,"name":"ruan","age":23,"date":new Date()}); }

hash分片结果测试
连接sh1
mongo --port 38021
use app 
db.vast.count();

连接sh2
mongo --port 38024
use app
db.vast.count();

分片操作

use admin
db.runCommand({ isdbgrid : 1})	判断是否Shard集群
db.runCommand({ listshards : 1})	列出所有分片信息
db.printShardingStatus()	查看分片的详细信息

列出开启分片的数据库
use config
db.databases.find( { "partitioned": true } ) 或者 db.databases.find() //列出所有数据库分片情况
db.collections.find().pretty()	查看分片的片键

删除分片节点(谨慎)
sh.getBalancerState()	确认blance是否在工作
db.runCommand( { removeShard: "shard2" } )	删除shard2节点(谨慎)
删除操作一定会立即触发blancer!!!

balancer操作

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

什么时候工作?
1、自动运行,会检测系统不繁忙的时候做迁移
2、在做节点删除的时候,立即开始迁移工作
3、balancer只能在预设定的时间窗口内运行

关闭和开启blancer(备份的时候)

mongos> sh.stopBalancer()
mongos> sh.startBalancer()

预设定的时间做balancer

连接到其中一个mongos
mongo --port 38017 admin

use config	
sh.setBalancerState( true )
// 每天3-5点
db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "3:00", stop : "5:00" } } }, true )

sh.getBalancerWindow()	// 查看balancer时间窗口
sh.status()

关于集合的balancer

关闭某个集合的balance

sh.disableBalancing("test.vast")

打开某个集合的balancer

sh.enableBalancing("test.vast")

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

db.getSiblingDB("config").collections.findOne({_id : "test.vast"}).noBalance;

备份与恢复

备份工具

mongoexport/mongoimport 导入/导出的是JSON格式或者CSV格式
mongodump/mongorestore 导入/导出的是BSON格式

JSON可读性强但体积较大,BSON则是二进制文件,体积小但对人类几乎没有可读性。

版本兼容性问题

在一些mongodb版本之间,BSON格式可能会随版本不同而有所不同,所以不同版本之间用mongodump/mongorestore可能不会成功,具体要看版本之间的兼容性。当无法使用BSON进行跨版本的数据迁移的时候,使用JSON格式即mongoexport/mongoimport是一个可选项。
跨版本的mongodump/mongorestore个人并不推荐,实在要做请先检查文档看两个版本是否兼容(大部分时候是不兼容的)

注意JSON虽然具有较好的跨版本通用性,但其只保留了数据部分,不保留索引,账户等其他基础信息。使用时应该注意。

应用场景

mongoexport/mongoimport:json csv
1、异构平台迁移 mysql <---> mongodb
2、同平台,跨大版本:mongodb 2 ----> mongodb 3

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

导出工具mongoexport

Mongodb中的mongoexport工具可以把一个collection导出成JSON格式或CSV格式的文件。
可以通过参数指定导出的数据项,也可以根据指定的条件导出数据。
(1)版本差异较大
(2)异构平台数据迁移

参数说明

mongoexport --help  
参数说明:
-h:指明数据库宿主机的IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明collection的名字
-f:指明要导出那些列
-o:指明到要导出的文件名
-q:指明导出数据的过滤条件
--authenticationDatabase admin

单表备份至json格式

备份文件的名字可以自定义,默认导出了JSON格式的数据。

mongoexport -uroot -padmin --port 27017 --authenticationDatabase admin -d app -c app -o /mongodb/bak/app.json

单表备份至csv格式

导出CSV格式的数据,需要使用--type=csv参数

-f导出的列头

mongoexport -uroot -padmin --port 27017 --authenticationDatabase admin -d app -c app --type=csv -f id  -o /mongodb/bak/app.csv

导入工具mongoimport

Mongodb中的mongoimport工具可以把一个特定格式文件中的内容导入到指定的collection中。该工具可以导入JSON格式数据,也可以导入CSV格式数据。

参数说明

mongoimport --help
参数说明:
-h:指明数据库宿主机的IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明collection的名字
-f:指明要导入那些列
-j, //并行多少CPU

恢复json格式表数据

mongoimport -uroot -padmin --port 27017 --authenticationDatabase admin -d app -c test1 /mongodb/bak/app.json

恢复csv格式的文件

csv格式的文件头行,有列名字
mongoimport   -uroot -padmin --port 27017 --authenticationDatabase admin   -d app -c test2 --type=csv --headerline --file  /mongodb/bak/app.csv

csv格式的文件头行,没有列名字
mongoimport   -uroot -padmin --port 27017 --authenticationDatabase admin   -d app -c test3 --type=csv -f id --file  /mongodb/bak/app.csv

异构平台迁移

mysql迁移mongodb

mysql开启安全路径
vim /etc/my.cnf   --->添加以下配置
secure-file-priv=/tmp

重启数据库生效
systemctl restart mysql

导出mysql的表数据
select * from app.user into outfile '/tmp/user.csv' fields terminated by ',';
#fields terminated by ','    字段间以,号分隔
#####其它参数
#optionally enclosed by '"'   字段用"号括起
#escaped by '"'            字段中使用的转义符为"
#lines terminated by '\r\n';  行以\r\n结束

处理csv文件
vim /tmp/user.csv   ----> 添加对应第一行列名信息

mongodb中导入csv文件
mongoimport -uroot -padmin --port 27017 --authenticationDatabase admin -d app  -c user --type=csv --headerline --file  /tmp/user.csv

BSON工具介绍

mongodump能够在Mongodb运行时进行备份,它的工作原理是对运行的Mongodb做查询,然后将所有查到的文档写入磁盘。但是存在的问题时使用mongodump产生的备份不一定是数据库的实时快照,如果我们在备份时对数据库进行了写入操作,则备份出来的文件可能不完全和Mongodb实时数据相等。另外在备份时可能会对其它客户端性能产生不利的影响。

导出工具mongodump

参数说明

mongodump --help
参数说明:
-h:指明数据库宿主机的IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明collection的名字
-o:指明到要导出的文件名
-q:指明导出数据的过滤条件
-j n 并行n个CPU
--oplog  备份的同时备份oplog

全库备份

mongodump  -uroot -padmin --port 27017 --authenticationDatabase admin -o /mongodb/bak

备份单库

mongodump   -uroot -padmin --port 27017 --authenticationDatabase admin -d app -o /mongodb/bak

备份库下的集合

mongodump   -uroot -padmin --port 27017 --authenticationDatabase admin -d app -c test3 -o /mongodb/bak

压缩备份

mongodump  -uroot -padmin --port 27017 --authenticationDatabase admin -o /mongodb/bak --gzip
mongodump  -uroot -padmin --port 27017 --authenticationDatabase admin -d app -o /mongodb/bak --gzip
mongodump  -uroot -padmin --port 27017 --authenticationDatabase admin -d app -c test3 -o /mongodb/bak --gzip

导入工具mongorestore

参数说明

mongorestore --help
参数说明:
-h:指明数据库宿主机的IP
-u:指明数据库的用户名
-p:指明数据库的密码
-d:指明数据库的名字
-c:指明collection的名字
--drop表示恢复的时候把之前的集合drop掉(危险)
--oplogReplay 同时导入oplog文件

恢复全部

mongorestore -uroot -padmin --port 27017 --authenticationDatabase admin /mongodb/bak

恢复库

mongorestore -uroot -padmin --port 27017 --authenticationDatabase admin -d app /mongodb/bak/app

恢复库下的集合

mongorestore -uroot -padmin --port 27017 --authenticationDatabase admin -d app -c app  /mongodb/bak/app/app.bson.gz

--drop恢复

mongorestore   -uroot -padmin --port 27017 --authenticationDatabase admin -d app --drop /mongodb/bak/app 

oplog介绍

mongodump和mongorestore对replica set或者master/slave使用

在replica set中oplog是一个定容集合(capped collection),它的默认大小是磁盘空间的5%(可以通过--oplogSizeMB参数修改)
oplog其中记录的是整个mongod实例一段时间内数据库的所有变更(插入/更新/删除)操作。当空间用完时新记录自动覆盖最老的记录。其覆盖范围被称作oplog时间窗口。需要注意的是,因为oplog是一个定容集合,所以时间窗口能覆盖的范围会因为你单位时间内的更新次数不同而变化。
想要查看当前的oplog时间窗口预计值,可以使用以下命令:

> rs.printReplicationInfo()
configured oplog size:   2048MB <--集合大小
log length start to end: 60295secs (16.75hrs) <--预计窗口覆盖时间
oplog first event time:  Sat Apr 17 2021 00:26:26 GMT+0800 (CST)
oplog last event time:   Sat Apr 17 2021 17:11:21 GMT+0800 (CST)
now:                     Sat Apr 17 2021 17:11:29 GMT+0800 (CST)

查看oplog的详细信息

use local 
db.oplog.rs.find().pretty()

oplog应用

实现热备,在备份时使用--oplog选项,--oplog 会记录备份过程中的数据变化,会以oplog.bson保存下来

mongodump --port 28017 --oplog -o /mongodb/bak

ls /mongodb/bak/
admin  oplog.bson

恢复

mongorestore  --port 28017 --oplogReplay /mongodb/bak

oplog使用示例

背景:每天0点全备,oplog恢复窗口为48小时
某天,上午10点业务表被误删除。

恢复思路:
1、停应用
2、找测试库
3、恢复昨天晚上全备
4、截取全备之后到world.city误删除时间点的oplog,并恢复到测试库
5、将误删除表导出,恢复到生产库

恢复步骤

备份现有的oplog.rs表
mongodump --port 28017 -d local -c oplog.rs  -o /mongodb/bak

截取oplog并恢复到drop之前的位置
mongo --port 28017
use local
db.oplog.rs.find({op:"c"}).pretty();
-----------------
op的值说明:
    "i": insert
    "u": update
    "d": delete
    "c": db cmd
假设误删命令是db.test.drop() 这里选”c“做关键查询
-----------------
获取到oplog误删除时间点位置
"ts" : Timestamp(1111111111, 1)  获取时间这一关键段

恢复备份+oplog.bson
ls /mongodb/bak/local/
oplog.rs.bson  oplog.rs.metadata.json

cp /mongodb/bak/local/oplog.rs.bson /mongodb/bak/oplog.bson
rm -rf /mongodb/backup/local/
mongorestore --port 28018  --oplogReplay --oplogLimit "1111111111:1"  --drop   /mongodb/bak/
即可恢复误删的集合

分片集群的备份思路

要备份什么?

config server
shard 节点
---单独进行备份

备份有什么困难和问题?

(1)chunk迁移的问题
人为控制在备份的时候,避开迁移的时间窗口
(2)shard节点之间的数据不在同一时间点。
选业务量较少的时候
posted @ 2021-04-17 17:40  rxg456  阅读(66)  评论(0)    收藏  举报