文档数据库--MongoDB

在这里插入图片描述

MongoDB介绍

MongoDB并非芒果mango的意思,而是源于Humongous(巨大的)一词。

MongoDB是由总部位于美国纽约的上市公司MongoDB lnc(原名10gen)基于C++编写的分布式文档数据库。
之所以称为文档数据库,是因为MongoDB保存的是"JSON Document",并非一般的PDF,WORD文档。MongoDB内部使用类似于Json的bson格式。

内部执行引擎为JS解释器。把文档存储成bson结构,在查询时转换为JS对象,并可以通过熟悉的js语法来操作。
MongoDB被称为最像RDBMS的NoSQL,支持事务,锁,索引类似于MySQL。

官方网站:https://www.mongodb.com/
Github:https://github.com/mongodb

在这里插入图片描述

数据库排名
https://db-engines.com/en/ranking
https://db-engines.com/en/ranking_trend/system/MongoDB
在这里插入图片描述
在这里插入图片描述

主要用途和特点

主要用途
  1.应用数据库,比如:存储银行,保险公司流水信息,类似于Oracle,MySQL海量数据处理,大数据分析
  2.网站数据、缓存等大尺寸、低价值的数据
  3.在高伸缩性的场景,用于对象及JSON数据的存储。
主要特点
  1.灵活动态的文档建模
  2.JSON数据模型比较适合开发者
  3.支持高可用
  4.水平扩展可以支撑很大数据量和并发
  5.存储空间占用相对关系型数据库会小很多
缺点:
  1.多表关联:仅仅支持Left Outer Join
  2.SQL语句支持:查询为主,部分支持
  3.多表原子事务:不支持
  4.多文档原子事务:不支持
  5.16MB文档大小限制,不支持中文排序
  6.服务端Javascript性能欠佳

对比关系型数据库

在这里插入图片描述

和关系型数据库最大的不同

MongoDB和关系型数据库最大的不同:
1.传统型数据库:结构化数据,定好了表结构后,每一行的内容必须符合表结构,就是说一列的个数和类型都一样;

2.MongoDB文档型数据库:表中的每个文档都可以有自己独特的结构,即json对象都可以有自己独特的属性和值。

什么时候使用MongoDB

什么时候使用MongoDB
  1.数据量是有亿万级或者需要不断扩容
  2.需要2000-3000以上的读写每秒
  3.新应用,需求会变,数据模型无法确定
  4.需要整合多个外部数据源
  5.系统需要99.999%高可用
  6.系统需要大量的地理位置查询
  7.系统需要提供最小的latency
  8.管理的主要数据对象<10

MongoDB数据结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

MongoDB参考资料

官网帮助手册:https://www.mongodb.com/docs/manual/
博客:https://www.cnblogs.com/clsn/p/8214194.html
MongoDB中文社区:https://mongoing.com/
runoob.com教程:https://www.runoob.com/mongodb/mongodb-tutorial.html

MongoDB部署和访问

官方安装说明:https://www.mongodb.com/docs/manual/installation/

MongoDB支持各种系统安装

在这里插入图片描述

二进制安装

官方配置文件说明:https://www.mongodb.com/docs/manual/reference/configuration-options/

创建所需用户和组
useradd mongod

创建mongodb所需目录结构
mkdir -p /mongodb/{conf, data, log}

创建YAML格式的配置文件,早期3.0版本以前是普通文本格式
cat > /mongodb/conf/mongo.conf <<EOF

日志相关
systemLog:
  destination: file
  path: "/mongodb/log/mongodb.log"       日志位置
  logAppend: true                        追加日志
  
数据存储有关
storage:
  dbPath: "/mongodb/data/"               数据路径的位置

进程控制
processManagement:
  fork: true                             后台守护进程
  
网络配置有关
net:
  port: 27017                            端口号,默认不配置端口号,是27017
  bindIp: 0.0.0.0                        监听地址自MongoDB 3.6版本后默认监听在localhost
  
#安全验证有关配置
security:
  authorization: enabled                 是否打开用户名密码验证,默认此项为关掉
EOF

cat /mongodb/conf/mongo.conf

systemLog:
  destination: file
  path: "/mongodb/log/mongodb.log"
  logAppend : true
storage :
  dbPath: "/mongodb/data/"
processManagement:
  fork : true
net:
  port: 27017
  bindIp: 0.0.0.0

脚本安装

#!/bin/bash
#
#********************************************************************
#Author:            wangxiaochun
#Date:              2021-02-19
#Filename:          install_mongodb.sh
#URL:               http://www.wangxiaochun.com
#Description:       The test script
#Copyright (C):     2021 All rights reserved
#********************************************************************

MONGODB_VERSOIN=rhel80-5.0.4
#MONGODB_VERSOIN=rhel70-5.0.3
#MONGODB_VERSOIN=ubuntu1804-5.0.3
#MONGODB_VERSOIN=ubuntu1804-4.4.4

MONGODB_FILE=mongodb-linux-x86_64-${MONGODB_VERSOIN}.tgz
#MONGODB_FILE=mongodb-linux-x86_64-ubuntu1804-4.4.4.tgz
URL=https://fastdl.mongodb.org/linux/$MONGODB_FILE
MONGODB_DIR=/mongodb
INSTALL_DIR=/usr/local
PORT=27017
MY_IP=`hostname -I|awk '{print $1}'`

. /etc/os-release

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}


system_prepare () {
    [ -e $MONGODB_DIR -o -e $INSTALL_DIR/mongodb ] && { color  "MongoDB 数据库已安装!" 1;exit; }
    if  [ $ID = "centos" -o $ID = "rocky" ];then
        rpm -q curl  &> /dev/null || yum install -y -q curl
    elif [ $ID = "ubuntu" ];then
        dpkg -l curl &> /dev/null || apt -y install curl
    else
        color  '不支持当前操作系统!' 1
        exit
    fi
    if [ -e /etc/rc.local ];then
        echo "echo never > /sys/kernel/mm/transparent hugepage/enabled" >> /etc/rc.local
    else
        cat > /etc/rc.local <<EOF
#!/bin/bash
echo never > /sys/kernel/mm/transparent hugepage/enabled
EOF
    fi
    chmod +x /etc/rc.local   
}

mongodb_file_prepare () {
    if [ ! -e $MONGODB_FILE ];then
        curl -O  $URL || { color  "MongoDB 数据库文件下载失败" 1; exit; } 
    fi
}

install_mongodb () {
    id mongod &> /dev/null || useradd -m -s /bin/bash mongod
    tar xf $MONGODB_FILE -C $INSTALL_DIR
    ln -s $INSTALL_DIR/mongodb-linux-x86_64-${MONGODB_VERSOIN} $INSTALL_DIR/mongodb
    #mongod --dbpath $db_dir --bind_ip_all --port $PORT --logpath $db_dir/mongod.log --fork
}

config_mongodb(){
    echo PATH=$INSTALL_DIR/mongodb/bin/:'$PATH' > /etc/profile.d/mongodb.sh
    . /etc/profile.d/mongodb.sh
    mkdir -p $MONGODB_DIR/{conf,data,log}
    cat > $MONGODB_DIR/conf/mongo.conf <<EOF
systemLog:
  destination: file
  path: "$MONGODB_DIR/log/mongodb.log"
  logAppend: true

storage:
  dbPath: "$MONGODB_DIR/data/"
  journal:
    enabled: true
 
processManagement:
  fork: true

net:
  port: 27017
  bindIp: 0.0.0.0
EOF
    chown -R  mongod.mongod $MONGODB_DIR/
    cat > /lib/systemd/system/mongod.service <<EOF
[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
User=mongod
Group=mongod
ExecStart=$INSTALL_DIR/mongodb/bin/mongod --config $MONGODB_DIR/conf/mongo.conf
ExecReload=/bin/kill -s HUP \$MAINPID
ExecStop=$INSTALL_DIR/bin/mongod --config $MONGODB/conf/mongo.conf --shutdown
PrivateTmp=true
# file size
LimitFSIZE=infinity
# cpu time
LimitCPU=infinity
# virtual memory size
LimitAS=infinity
# open files
LimitNOFILE=64000
# processes/threads
LimitNPROC=64000
# locked memory
LimitMEMLOCK=infinity
# total threads (user+kernel)
TasksMax=infinity
TasksAccounting=false
# Recommended limits for mongod as specified in
# https://docs.mongodb.com/manual/reference/ulimit/#recommended-ulimit-settings

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload
    systemctl enable --now  mongod &>/dev/null
}

start_mongodb() { 
    systemctl is-active mongod.service &>/dev/null
    if [ $?  -eq 0 ];then  
        echo 
        color "MongoDB 安装完成!" 0
    else
        color "MongoDB 安装失败!" 1
        exit
    fi 
}

system_prepare 
mongodb_file_prepare
install_mongodb
config_mongodb
start_mongodb

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

MongoDB后台管理shell

如果需要进入mongodb后台管理,可以先打开mongodb装目录的下的 bin目录,然后执行mongo命令文件。

MongoDB Shell是MongoDB自带的交互式Javascript shell,用来对MongoDB进行操作和管理的交互式环境。

mongo是MongoDB早期版本使用的shell工具,将来会被mongosh替代。

在这里插入图片描述
当mongo进入mongoDB后台后,它默认会链接到test数据库,使用db命令可以查看
在这里插入图片描述

mongodb数据库命令

mongo的help

在这里插入图片描述

db.mycoll.help()

在这里插入图片描述

mongosh的help

在这里插入图片描述

show dbs

在这里插入图片描述

use dbname

use命令后直接跟一个名称就可以创建这个名称的数据表(如下截图),不像mysql必须先创建数据表才能use
在这里插入图片描述

mongosh的安装

官方安装文档:https://www.mongodb.com/docs/mongodb-shell/install/

yum安装或者下载包安装
mongodb-mongosh-1.1.2.el8.x86_64.rpm

在这里插入图片描述
在这里插入图片描述

然后就可以使用mongosh
在这里插入图片描述

可视化管理工具

MongoDB Compass是MongoDB官网提供的一个可视化管理工具,可以实现创建数据库、管理集合和文档、运行临时查询、评估和优化查询、性能图表、构建地理查询等功能。

MongoDB Compass官网下载地址:https://www.mongodb.com/products/tools/compass
在这里插入图片描述
已经连接成功了
在这里插入图片描述
在这里插入图片描述

Python访问MongoDB

yum -y install python3
pip3 install pymongo

在这里插入图片描述
test_mongodb.py

#!/usr/bin/python3
from pymongo import MongoClient

# 客户端连接
#client = MongoClient(host='127.0.0.1', port=27017) 
client = MongoClient('mongodb://127.0.0.1:27017')
print(client)

# 指定数据库 # Database类
#db = client.test 
db = client['test']
print(db)

# 集合 # Collection类
#users = db['users']
users = db.users
print(users)

for i in range(10):
    user = {'id':i, 'name':'wang' + str(i), 'age':20}
    users.insert_one(user)
for x in users.find():
    print(x)
client.close()

在这里插入图片描述
使用show tables查看新增的数据

test> show tables
users

在这里插入图片描述
在这里插入图片描述

MongoDB管理

官方帮助手册:https://www.mongodb.com/docs/manual/crud/

库的操作

use可以自动建库,如果库内没有数据,则不使用时会自动删除库
>use test

删除当前所在库
> db.dropDatabase()
{ ok: 1, dropped: 'test' }

可以直接切换至不存在的库
>use testdb1
>db
testdb1

可以使用Tab键查看有哪些支持的命令

test> db.drop
db.dropDatabase  db.dropUser      db.dropAllUsers  db.dropRole      db.dropAllRoles

在这里插入图片描述

集合(表)的操作

灵活的insert

建表方法1:直接创建表
>db.createco1lection ('student ')

建表方法2:当插入一个文档的时候,一个集合就会自动创建。
插入一条数据
db.students.insertOne({
  item: 'canvas',
  qty: 100,
  tags: ['cotton'],
  size: { h: 28, w: 35.5, uom: 'cm' }
});

插入多条数据
db.students.insertMany([
  {
    item: 'journal',
    qty: 25,
    tags: ['blank', 'red'],
    size: { h: 14, w: 21, uom: 'cm' }
  },
  {
    item: 'mat',
    qty: 85,
    tags: ['gray'],
    size: { h: 27.9, w: 35.5, uom: 'cm' }
  },
  {
    item: 'mousepad',
    qty: 25,
    tags: ['gel', 'blue'],
    size: { h: 19, w: 22.85, uom: 'cm' }
  }
]);

此时我的数据库中已经有user表了,且表中有只有id,name,age字段,那么此时我插入下面这个记录会成功吗?

db.users.insertOne({
  item: 'canvas',
  qty: 100,
  tags: ['cotton'],
  size: { h: 28, w: 35.5, uom: 'cm' }
});

看,插入成功了! mysql这么操作的话是会报错的哦!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

查看库中的集合列表
show tables
show collections

在这里插入图片描述

查看集合的信息
db.students.stats()

在这里插入图片描述

删除集合
db.students.drop()

在这里插入图片描述

记录(文档操作)

数据录入:

 for (i = 0; i < 10000; i++) {db.student.insertOne({ uid: i, name: "lei" + i, "age": 18, "date": new Date() });}
for(i=0;i<10000;i++){db.users.insertOne({uid: i, name: "lei"+i, "age": i, address: "shenzhen"})}
for(i=0;i<10000;i++){db.random.insertOne({num: Math.random()* 100000})

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

查询数据行数
db.student.countDocuments()

在这里插入图片描述

只显示前三条
db.student.find().limit(3)

在这里插入图片描述

跳过前面5条记录显示后面的
db.student.find().skip(5)

在这里插入图片描述

db.student.find({uid:18})

在这里插入图片描述

查询大于等于18并正序排序的users集合,-1则是倒序

在这里插入图片描述
在这里插入图片描述

db.users.find({age: { $gte: 18 }},{ name: 1, address: 1}).limit(5)

在这里插入图片描述

db.student.deleteOne({uid: 12})

在这里插入图片描述

用户和权限管理

MongoDB数据库默认是没有用户名及密码的,即无权限访问限制。为了方便数据库的管理和安全,应启用认证和创建数据库用户。

官方帮助手册:https://www.mongodb.com/docs/manual/tutorial/create-users/

用户验证库

关于用户验证库
  1.创建用户时,use所在的库就是此用户的验证库
  2.登录时,必须明确指定验证库才能登录
  3.一个数据库可以成为多个用户的验证库,但一个用户只能使用一个验证库
  4.对于管理员用户,必须在admin下创建,即管理员用的验证库是admin
  5.普通用户的验证库一般是所管理的库
  6.如果直接登录到数据库,不进行use,默认的验证库是test
  7.从3.6版本开始,配置文件中不添加bindIp参数,默认不允许远程登录,只能本地管理员登录。

开启用户认证

在这里插入图片描述

#方法2,修改配置文件中,加入以下配置
cat >> /mongodb/conf/mongo.conf <<EOF
security:
  authorization: enabled
EOF

systemctl restart mongod

用户管理说明

use test
db.createUser(
  {
    user: "myTester",
    pwd:  passwordPrompt(),   // or cleartext password
    roles: [ { role: "readWrite", db: "test" },
             { role: "read", db: "reporting" } ]
  }
)

在这里插入图片描述

系统内置角色

官方帮助手册:https://www.mongodb.com/docs/manual/reference/built-in-roles/

在这里插入图片描述
在这里插入图片描述

superuser用户

创建超级管理员root(也可以是任意用户名)管理所有数据库(必须use admin再去创建,因为超级用户是存放在admin库中的)

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

在这里插入图片描述
验证superuser用户是否可以登录
在这里插入图片描述

普通用户

创建一个普通用户myTester,对test数据库有读写权限,对test2只有读的权限

db.createUser(
  {
    user: "myTester",
    pwd:  passwordPrompt(), 
    roles: [ { role: "readWrite", db: "test" },
             { role: "read", db: "test2" } ]
  }
)

在这里插入图片描述
在这里插入图片描述
验证myTester用户的登录
在这里插入图片描述
验证用户也可以不用去登录判断该用户是否生效,可以直接使用db.auth(‘用户名’,‘密码’)命令验证,返回ok:1则为用户创建成功。

db.auth('myTester', '123456')

在这里插入图片描述

验证myTester是否对test2有写权限
在这里插入图片描述

查看所有用户信息

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

要使用超级管理员在admin库中查看

test> use admin 
switched to db admin
admin> db.system.users.find().pretty()
[
  {
    _id: 'admin.superuser',
    userId: UUID("61b779dd-f242-4f2c-af0c-ffa29381023e"),
    user: 'superuser',
    db: 'admin',
    credentials: {
     ......
    },
    roles: [ { role: 'root', db: 'admin' } ]
  },
  {
    _id: 'test.myTester',
    userId: UUID("59dbc2ec-a171-4666-9f4a-ab8b49f97b04"),
    user: 'myTester',
    db: 'test',
    credentials: {
      ......
    },
    roles: [
      { role: 'read', db: 'test2' },
      { role: 'readWrite', db: 'test' }
    ]
  }
]
admin>

MongoDB复制集

MongDB像MySQL一样,支持类似的主从复制架构,但无法实现自动故障转移,所以官方推荐使用复制集。

MongoDB复制集是将数据同步在多个服务器的过程,复制集提供了数据的冗余备份,并在多个服务器上存储数据副本,保证数据的安全性。

复制集还允许从硬件故障和服务中断中恢复数据。当故障时,会自动选举新master节点实现集群的高可用。

官方帮助手册:https://www.mongodb.com/docs/manual/replication/

复制集架构

MongoDB的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,主节点接收所有写入操作。其余的都是从节点,负责复制主节点上的数据。

MongoDB各个节点常见的搭配方式为:一主一从、一主两从此方式最多。

主节点记录在其上的所有操作oplog(操作日志),从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

客户端写入数据到主节点时,主节点与从节点进行数据交互保障数据的一致性。

在这里插入图片描述

复制集特征:
  1.N个奇数节点的集群
  2.基于选举机制,任何节点可作为主节点
  3.所有写入操作都在主节点上,所以增加节点不会提高系统写性能,可以提升读性能
  4.主节点故障时,会自动选举出新节点代替,自动故障转移

复制集实现

复制集要求三个以上的MongoDB节点

我有三台机器154、155、156,都有安装好了MongoDB
在这里插入图片描述

1.配置mongo.conf文件

在三台主机的配置文件中分别加上以下配置
vim /mongodb/conf/mongo.conf

replication:
  replSetName: myrepl

示例

systemLog:
  destination: file
  path: "/mongodb/log/mongodb.log"
  logAppend: true

storage:
  dbPath: "/mongodb/data/"
  journal:
    enabled: true

processManagement:
  fork: true

net:
  port: 27017
  bindIp: 0.0.0.0

#security:
#  authorization: enabled

replication:
  replSetName: myrepl   制定复制集名称,所有复制集成员此名称要一致

2.初始化设置,

以下配置在三台主机中任意一台执行

config = { _id: 'myrepl', members: [
	{_id: 0, host: '192.168.10.154:27017'},
	{_id: 1, host: '192.168.10.155:27017'},
	{_id: 2, host: '192.168.10.156:27017'}]
	}

3.执行rs.initiate(初始化设置的函数名)

rs.initiate(config)

我在154这台机器上执行的
在这里插入图片描述
在这里插入图片描述
此时155和156上则显示SECONDARY
在这里插入图片描述

查看复制集状态

在这里插入图片描述

myrepl:PRIMARY> rs.isMaster()
{
	"topologyVersion" : {
		"processId" : ObjectId("66a78b7916704ef3521b7b5c"),
		"counter" : NumberLong(10)
	},
	"hosts" : [
		"192.168.10.154:27017",
		"192.168.10.155:27017",
		"192.168.10.156:27017"
	],
	"setName" : "myrepl",
	"setVersion" : 1,
	"ismaster" : true,
	"secondary" : false,
	"primary" : "192.168.10.154:27017",
	"me" : "192.168.10.154:27017",
	"electionId" : ObjectId("7fffffff0000000000000002"),
	"lastWrite" : {
		"opTime" : {
			"ts" : Timestamp(1722257856, 1),
			"t" : NumberLong(2)
		},
		"lastWriteDate" : ISODate("2024-07-29T12:57:36Z"),
		"majorityOpTime" : {
			"ts" : Timestamp(1722257856, 1),
			"t" : NumberLong(2)
		},
		"majorityWriteDate" : ISODate("2024-07-29T12:57:36Z")
	},
	"maxBsonObjectSize" : 16777216,
	"maxMessageSizeBytes" : 48000000,
	"maxWriteBatchSize" : 100000,
	"localTime" : ISODate("2024-07-29T12:57:40.021Z"),
	"logicalSessionTimeoutMinutes" : 30,
	"connectionId" : 1,
	"minWireVersion" : 0,
	"maxWireVersion" : 13,
	"readOnly" : false,
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(1722257856, 1),
		"signature" : {
			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
			"keyId" : NumberLong(0)
		}
	},
	"operationTime" : Timestamp(1722257856, 1)
}
myrepl:PRIMARY> 

slaveOk()

SECONDARY节点默认不提供访问,需要执行slaveOK()来打开访问设置
在这里插入图片描述
在这里插入图片描述
rs.slaveOk()将来会被rs.secondaryOk()取代
在这里插入图片描述
在这里插入图片描述

secondary节点只能读,不能写

在这里插入图片描述

添加和删除节点

删除一个节点
rs.remove ("ip: port")

新增从节点
rs.add ("ip: port")

#新增仲裁节点
rs.addArb ("ip: port")

示例

添加一个节点
myrepl:PRIMARY> rs.add ("192.168.10.157: 27017")

删除一个节点
myrepl:PRIMARY> rs.remove ("192.168.10.157: 27017")
{ "ok": 1 }

添加仲裁节点
myrepl:PRIMARY> rs.addArb ("192.168.10.158:27017")
myrepl:SECONDARY> db.isMaster()
{
	"hosts" : [
		"192.168.10.154:27017",
		"192.168.10.155:27017",
		"192.168.10.156:27017"
	],
	"arbiters" : [
	    "192.168.10.158:27017"
	],
}

复制集角色说明

主要角色

主节点[Primary]

接收所有的写请求,然后把修改同步到所有Secondary。一个Replica Set只能有一个Primary节点,当Primary挂掉后,其他Secondary或者Arbiter节点会重新选举出来一个主节点。默认读请求也是发到Primary节点处理的,如果需要转发到Secondary,需要在客户端修改一下连接配置。

副本节点[Secondary]

与主节点保持同样的数据集。当主节点挂掉的时候,可以参与选举出新主节点。

仲裁者[Arbiter]

不保存数据,不参与选主,只进行选主投票。使用Arbiter可以减轻数据存储的硬件需求,Arbiter跑起来几乎没什么大的硬件资源需求,在生产环境下它和其他数据节点不要部署在同一台机器上。实际生产环境当前不推存使用Arbiter节点类型

MongoDB使用Raft选举机制,而MySQL MGR 用的是Paxos,而Raft本质是Paxos的变种
注意,一个自动failover的Replica Set节点数必须为奇数,目的是选主投票的时候要有一个大多数才能进行选主决策。

Primary选举实现

复制集通过replSetInitiate命令(或mongo shell的rs.initiate())进行初始化,初始化后各个成员间开始发送心跳消息,并发起Primary选举操作,获得大多数成员投票支持的节点,会成为Primary,其余节点成为Secondary。

选举实现
  1.具有投票权的节点之间两两互相发送心跳
  2.当5次心跳未收到时,判断为节点失联
  3.如果失联的是主节点,从节点会发起选举,选出新的主节点
  4·如果失联的是从节点则不会产生新的选举
  5.选举基于RAFT一致性算法实现,选举成功的必要条件是大多数投票节点存活
  6.复制集中最多可以有50个节点,但具有投票权的节点最多7个,且为奇数个投票成员

大多数的定义
假设复制集内投票成员(后续介绍)数量为N,则大多数为N/2+1,当复制集内存活成员数量不足大多数时,整个复制集将无法选举出Primary,复制集将无法提供写服务,处于只读状态。
在这里插入图片描述
通常建议将复制集成员数量设置为奇数,从上表可以看出3个节点和4个节点的复制集都只能容忍1个节点失效,从服务可用性的角度看,其效果是一样的。(但无疑4个节点能提供更可靠的数据存储)

被选举为主节点的节点必须:
  1.能够与多数节点建立连接
  2.具有较新的oplog
  3.具有较高的优先级(如果有配置)

其他角色

在这里插入图片描述

rs.conf()查看优先级

在这里插入图片描述

MongoDB备份恢复

虽然有复制集的高可用性保证,数据丢失的可能很低,但仍然需要备份。

备份的目的:
  1.防止硬件故障引起的数据丢失
  2.防止人为错误误删数据
  3.时间回溯
  4.监管要求

备份恢复的两个工具

1.mongoexport/mongoimport

mongoexport/mongoimport可以实现逻辑备份,类似于mysqldump,可以导出json或csv格式文件

应用场景总结
  1.异构平台迁移,比如:MySQL和MongoDB
  2.同平台跨大版本的MongoDB数据导出导入:比如mongodb 2 ----> mongodb 3

2.mongodump/mongorestore

物理备份,日常备份恢复时使用,导出的二进制文件。

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

使用mongodump备份最灵活,但速度上也是最慢的

mongodump出来的数据不能表示某个时间点,只是某个时间段
在这里插入图片描述

两种工具的对比

mongoexport/mongoimport导入/导出的是JSON格式
而mongodump/mongorestore导入/导出的是BSON格式。

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

在一些mongodb版本之间,BSON格式可能会随版本不同而有所不同,所以不同版本之间用mongodump/mongorestore可能不会成功,具体要看版本之间的兼容性。

当无法使用BSON进行跨版本的数据迁移的时候,使用JSON格式即mongoexport/mongoimport是一个可选项。

跨版本的mongodump/mongorestore并不推荐,实在要做请先检查文档看两个版本是否兼容。
JSON虽然具有较好的跨版本通用性,但其只保留了数据部分,不保留索引,账户等其他基础信息。

mongoexport/mongoimport

导出工具 mongoexport

此工具只能针对单表,不支持整库的表导出

官方帮助手册:https://www.mongodb.com/docs/database-tools/mongoexport/

下载链接:https://www.mongodb.com/try/download/database-tools

我下载的是rpm包

yum -y install  mongodb-database-tools-rhel80-x86_64-100.5.1.rpm

可以使用一下命令,查看导出导出工具

rpm -ql mongodb-database-tools

在这里插入图片描述
mongoexport具体用法使用"mongoexport --help"查看帮助,部分参数使用如下所示:

[root@rocky ~]# mongoexport --help
参数说明:
-h   指明数据库宿主机的IP
-u   指明数据库的用户名
-p   指明数据库的密码
-d   指明数据库的名字
-c   指明co1lection的名字
-f   指明要导出那些列
-o   指明到要导出的文件名
-q   指明导出数据的过滤条件
--type=Csv或--csv   指定导出为csv格式,默认json格式
--authenticationDatabase<验证库>   指定验证库
导出json格式示例

目前在test库中有一张users表,表中有一万条记录
在这里插入图片描述

mongoexport -d test -c users -o /backup/users.json

在这里插入图片描述
使用wc -l 查看下导出的文件有多少行
在这里插入图片描述
在这里插入图片描述

导出csv格式示例

导出test库中userStore表的一万条记录为csv格式
在这里插入图片描述

mongoexport -d test -c userStore --type=csv -f uid,name,age,address -o /backup/users.csv

导出成功了
在这里插入图片描述
查看一下导出的users.csv文件的样子
在这里插入图片描述

导入工具mongoimport

官方帮助手册:https://www.mongodb.com/docs/database-tools/mongoimport/

[root@rocky ~]# mongoimport --help
Usage:
  mongoimport <options> <connection-string> <file> 

Import CSV, TSV or JSON data into MongoDB. If no file is provided, mongoimport reads from stdin.

Connection strings must begin with mongodb:// or mongodb+srv://.

See http://docs.mongodb.com/database-tools/mongoimport/ for more information.

参数说明:
-h      指明数据库宿主机的IP
-u      指明数据库的用户名
-p      指明数据库的密码
-d      指明数据库的名字
-c      指明co1lection的名字-f#指明要导入那些列
--type=csv   指定导入cSv格式文件,默认json格式
-j,--numInsertionworkers=<number>    同时插入的数量,默认为
--headerline   指明第一行是列名,不需要导入
导入示例

1.删除users表
在这里插入图片描述
2.将/backup/users.json 数据导入到userStore表中,userStore表不存在则会自动创建。

mongoimport -d test -c userStore /backup/users.json 

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

将Mysql数据迁移至MongoDB

1.mysql开启安全路径

vim /etc/my.cnf

[root@rocky ~]# vim /etc/my.cnf
[mysqld]
secure-file-priv=/tmp

2.注释掉PrivateTmp=true

vim /usr/lib/systemd/system/mysqld.service

[root@rocky ~]# vim /usr/lib/systemd/system/mysqld.service
将此行注释,否则会在/tmp/生成一个随机字符串的临时的子目录,不好找!
#PrivateTmp=true 

之后重启mysqld

 systemctl daemon-reload
 systemctl restart mysqld

在这里插入图片描述

3.导出mysql的数据表为csv文件

导出hellodb数据库的students表
在这里插入图片描述

默认导出为Tab分隔的csv文件
mysql> select * from hellodb.students into outfile '/tmp/students.csv ';

指定导出分隔符为','的csv文件
mysql> select * from hellodb.students into outfile '/tmp/students.csv' fields terminated by ',';

在这里插入图片描述
查看/tmp目录下的students.csv
在这里插入图片描述

4.导出mysql数据表的列名

如果列很多,可以使用infomation_schema.columns导出列名
select column_name from information_schema.columns where table_schema= 'hellodb' and table_name='students';

在这里插入图片描述
在这里插入图片描述

group_concat函数可以多行合并成一行显示
select group_concat(column_name) from information_schema.columns where table_schema='hellodb' and table_name='students';

在这里插入图片描述

5.在mongodb中导入mysql的csv文件

5.1将第4步查出的列名加入到前面导出的文件students.csv的第一行
vim /tmp/students.csv
在这里插入图片描述

如果开启了用户登录验证则使用一下命令

mongoimport -uroot -p123456 --port 27017 --authenticationDatabase admin -d test -c students --type=csv --header1ine --file /tmp/studentsMysql.csv

没有开启用户登录验证

mongoimport -d test -c mysqlMigrate --type=csv --headerline --file /tmp/studentsMysql.csv

在这里插入图片描述
看出数据是否导入到mongodb中了
在这里插入图片描述

5.2使用选项 -f 指定列名

mongoimport -uroot -p123456 --port 27017 --authenticationDatabase admin -d test -c mysqlMigrate --type=csv -f StuID, Name,Age ,cender, classID, TeacherID --file /tmp/students.csv
mongoimport -d test -c mysqlMigrate --type=csv -f StuID, Name,Age ,cender, classID, TeacherID --file /tmp/studentsMysql.csv

mongodump和mongorestore

mongodump

官方帮助手册:https://www.mongodb.com/docs/database-tools/mongodump/

mongodump用法如下:

mongodump --help
参数说明:
-h     指明数据库宿主机的IP
-u     指明数据库的用户名
-p     指明数据库的密码
-d     指明数据库的名字
-c     指明co1lection的名字
-o     指明到要导出的文件名
-q     指明导出数据的过滤条件
-j,--numPara11e1co1lections=   并行导出的数量,默认为4
--oplog      备份的同时备份oplog,此选项是replica set或者master/slave模式专用
导出规律
  1.导出的文件放在以database命名的目录下
  2.每个表导出2个文件;分别是bson结构的数据文件和json格式的索引信息
  3.如果不声明表名。导出所有的表

示例

全库备份
注意:完全备份不会备份config和local库,但会备份admin库和test库及用户库
mkdir -p /backup/full
mongodump -uroot -p123456 --port 27017 --authenticationDatabase admin -o/backup/full
mongodump -uroot -p123456 --port 27017 --authenticationDatabase admin -o/backup/full-`date +%F`

备份指定库test
mkdir -p /backup/test_backup
mongodump -uroot -p123456 --port 27017 --authenticationDatabase admin -d test -o /backup/test_backup

备份magedu库下的vast集合
mkdir -p /backup/vast
mongodump -uroot -p123456 --port 27017 --authenticationDatabase admin -d magedu -c vast -o /backup/vast

完全备份并压缩备份
mkdir -p /backup/full_gzip
mongodump -uroot -p123456 --port 27017 --authenticationDatabase admin -o /backup/full_gzip --gzip

mongorestore

官方帮助文档:https://www.mongodb.com/docs/database-tools/mongorestore/

mongorestore与mongoimport参数类似

mongorestore用法如下:

mongorestore --help
-h    指明数据库宿主机的IP
-u    指明数据库的用户名
-p    指明数据库的密码
-d    指明数据库的名字
-c    指明co1lection的名字
-o    指明到要导出的文件名
-q    指明导出数据的过滤条件
--authenticationDatabase     验证数据的名称--gzip#备份时压缩
--oplogReplay       恢复完数据文件后再重放oplog。默认重放dump/oplog.bson--oplogFile=<filename>#指定需要重放的op1og文件位置
--oplogLimit=<seconds>[:ordinal]   重放oplog 时截止到指定时间点
--drop     恢复的时候把之前的集合drop掉

示例

恢复完全备份
mongorestore -uroot -p123456 --port 27017 --authenticationDatabase admin/backup/full

从完全备份的压缩备份中的test库恢复至test1库
mongorestore -uroot -p123456 --port 27017 --authenticationDatabase admin -dtest1 /backup/fu77_gzip/test --gzip

从完全备份中的vast表恢复到test库中的test库的表vast1中
mongorestore-uroot -p123456--port 27017 --authenticationDatabase admin -d test-c vast1 --gzip /backup/fu17_gzip/test/vast.bson.gz

默认不允许覆盖恢复会报错,可以使用选项--drop实现覆盖恢复,表示恢复的时候先之前的集合drop掉(危险),再恢复
mongorestore -uroot -p123456 --port 27017 --authenticationDatabase admin -dmagedu --drop /backup/magedu

oplog恢复数据

官方帮助手册:https://www.mongodb.com/docs/manual/core/replica-set-oplog/

oplog类似于MySQL中的binlog,记录了MongoDB数据的更新,只支持复制集,不支持单节点。

在replica set中oplog是一个定容集合(capped collection,固定大小),保存在local库的db.oplog.rs

它的默认大小是磁盘空间的5%(可以通过–oplogsizeMB参数修改).

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

其覆盖范围被称作op1og时间窗口。

需要注意的是,因为oplog是一个定容集合,所以时间窗口能覆盖的范围会因为单位时间内的更新次数不同而变化。
至少要预留MongoDB的1个全备的周期大小。

默认情况下,MongoDB不设置最小oplog 保留期,并自动从最旧的条目开始截断 oplog,以保持配置的最大 oplog大小。

oplog有一个非常重要的特性–幂等性(idempotent)。即对一个数据集合,使用oplog中记录的操作重放时,无论被重放多少次,其结果会是一样的。比如,如果oplog中记录的是一个插入操作,并不会因为你重放了两次,数据库中就得到两条相同的记录。这是一个很重要的特性.
在这里插入图片描述

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值