MongoDB是由C++语言编写一个基于分布式文件存储的开源NoSQL数据库系统。在高负载的情况下,可添加更多的节点(实例),以保证服务性能。在许多场景下用于代替传统的关系型数据库或键/值存储方式。旨在为Web应用提供可扩展的高性能数据存储解决方案
MongoDB提供了一个面向文档存储方式,操作起来比较简单和容易,可以存储比较复杂的数据类型。最大的特点是支持的查询语言功能非常强大,语法类似于面向对象的查询(Select)语言。几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。是一个面向集合的,模式自由的文档型数据库。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的
MongoDB目前只支持单文档事务,需要复杂事务支持的场景暂时不适合,灵活的文档模型JSON 格式存储最接近真实对象模型,对开发者友好,方便快速开发迭代。高可用复制集满足数据高可靠、服务高可用的需求,运维简单,故障自动切换可扩展分片集群海量数据存储,服务能力水平扩展高性能。mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持满足各种场景需求强大的索引支持地理位置索引可用于构建各种O2O 应用、文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求、Gridfs解决文件存储的需求、aggregation & mapreduce解决数据分析场景需求,用户可以自己写查询语句或脚本,将请求都分发到MongoDB 上完成
从目前阿里云MongoDB 云数据库上的用户应用分析MongoDB的应用已经渗透到各个领域,比如游戏、物流、电商、内容管理、社交、物联网、视频直播等,以下是几个实际的应用案例。
- - 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存 储,方便查询、更新。
- - 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
- - 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索 引实现附近的人、地点等功能。
- - 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对 这些信息进行多维度的分析。
- - 视频直播,使用 MongoDB 存储用户信息、礼物信息等
- - 文档(document)是MongoDB中数据的基本单元,非常类似于关系型数据库系统中的行(记录)但是比行存储的数据要复杂的多。
- - 集合(collection)就是一组文档组成,如果说MongoDB中的文档类似于关系型数据库中的行,那么集合就如同数据表。
- - MongoDB的单个实例可以容纳多个独立的数据库,每一个数据库都有自己的集合和权限。
MongoDB自带简洁但功能强大的JavaScript shell,这个工具对于管理MongoDB实例和操作数据作用非常大。
每一个文档都有一个特殊的键”_id”,它在文档所处的集合中是唯一的,相当于关系数据库中的表的主键
SQL术语/概念 |
MongoDB术语/概念 |
解释/说明 |
database |
database |
数据库 |
table |
collection |
数据库表/集合 |
row |
document |
数据记录行/文档 |
column |
field |
数据字段/域 |
index |
index |
索引 |
table joins |
表连接,MongoDB不支持 |
|
primary key |
primary key |
主键,MongoDB自动将_id字段设置为主键 |
数据库命名规范:
数据库名可以是满足以下条件的任意UTF-8字符串。
集合命名规范:
文档键命名规范:
为了更好的识别系统名改为MongoDB
hostnamectl set-hostname MongoDB
bash
首先关闭防火墙
iptables -F
setenforce 0
systemctl stop firewalld
指定一个进程同一时间最多可开启的文件数
[root@mongodb ~]# ulimit -n
显示当前进程的最大文件描述符数量限制
[root@mongodb ~]# ulimit -n 65535
[root@mongodb ~]# ulimit -n
ulimit 命令的设置只对当前会话有效,当用户退出登录后,设置会失效。如果需要永久性地修改文件描述符限制,需要修改系统的配置文件
用户最多可开启的进程数目
[root@mongodb ~]# ulimit -u
[root@mongodb ~]# ulimit -u 65535
[root@mongodb ~]# ulimit -u
安装版本下载地址
[root@mongodb ~]#
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.6.tgz
[root@mongodb ~]# tar xf mongodb-linux-x86_64-rhel70-4.0.6.tgz
[root@mongodb ~]# mv mongodb-linux-x86_64-rhel70-4.0.6 /usr/local/mongodb
[root@mongodb ~]# ln -s /usr/local/mongodb/bin/* /bin/
[root@mongodb ~]# mkdir -p /data/mongodb1 //数据目录
[root@mongodb ~]# mkdir -p /data/logs/mongodb //日志目录
[root@mongodb ~]# touch /data/logs/mongodb/mongodb1.log //日志文件
[root@mongodb ~]# cd /usr/local/mongodb/
[root@mongodb mongodb]# mkdir conf //配置文件目录
[root@mongodb mongodb]# vim conf/mongodb1.conf //配置文件
port=27017 //监听端口
dbpath=/data/mongodb1 //指定数据目录
logpath=/data/logs/mongodb/mongodb1.log //指定日志文件路径
logappend=true //允许写入日志
fork=true //允许创建子进程
maxConns=5000 //最大连接数
storageEngine=mmapv1 //存储引擎
启动MongoDB数据库,-f指定配置文件
[root@mongodb ~]#
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/mongodb1.conf
用于启动 MongoDB 数据库服务器。具体含义如下:
`/usr/local/mongodb/bin/mongod`:指定 MongoDB 服务器的可执行文件路径。 `
-f /usr/local/mongodb/conf/mongodb1.conf`:指定配置文件的路径和文件名。在这个例子中,配置文件为 `/usr/local/mongodb/conf/mongodb1.conf`。 通过执行这个命令,你可以启动 MongoDB 数据库服务器,并使用指定的配置文件进行配置
[root@mongodb ~]# netstat -lnpt | grep mongod
查找并显示与 MongoDB 相关的监听状态和对应的进程信息
[root@mongodb ~]# ps aux | grep mongod | grep -v grep
找正在运行的mongod进程。具体解释如下:
- `ps aux`:显示当前系统中所有正在运行的进程。
- `grep mongod`:在进程列表中过滤出包含"mongod"关键字的行。
- `grep -v grep`:再次过滤掉包含"grep"关键字的行,以排除grep命令本身的输出。
综合起来,该命令的作用是查找并显示当前正在运行的mongod进程,同时排除掉grep命令本身的输出
设置开机自动启动
[root@mongodb mongodb]# vim /etc/rc.local
写入:
rm -f /data/mongodb1/mongod.lock
mongod -f /usr/local/mongodb/conf/mongodb1.conf
这条命令的作用是删除指定路径下的 `mongod.lock` 文件,然后使用指定的配置文件启动 MongoDB 数据库服务
连接数据库
[root@mongodb ~]# mongo
> show dbs
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
关闭MongoDB的方式:
方法一:
[root@mongodb ~]# mongo
> use admin
> db.shutdownServer(); //关闭服务
> exit
[root@mongodb ~]# netstat -anpt |grep mongod
显示所有与 MongoDB 相关的 TCP 连接,并显示与这些连接相关的进程信息
显示所有与 MongoDB 相关的 TCP 连接,并显示与这些连接相关的进程信息发现没有 已经关闭
方法二:
[root@mongodb ~]#
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/mongodb1.conf
启动 MongoDB 数据库服务器(先启动数据库再进行以下操作)
[root@mongodb ~]# netstat -lnpt | grep mongod
查询当前系统中所有监听状态的连接,并筛选出包含 "mongod" 的行,即查找与 MongoDB 相关的连接
[root@mongodb ~]# /usr/local/mongodb/bin/mongod -f
/usr/local/mongodb/conf/mongodb1.conf --shutdown
用于关闭 MongoDB 数据库。具体解释如下:
- `/usr/local/mongodb/bin/mongod` 是 MongoDB 数据库的可执行文件路径。
- `-f /usr/local/mongodb/conf/mongodb1.conf` 是指定 MongoDB 配置文件的路径和文件名。 - `--shutdown` 是一个选项,表示执行关闭数据库的操作。
所以,这条命令的含义是使用指定的配置文件关闭 MongoDB 数据库
[root@mongodb ~]# netstat -lnpt | grep mongod
显示所有与 MongoDB 相关的 TCP 连接,并显示与这些连接相关的进程信息
netstat -lnpt | grep mongod查看不显示进程关闭成功
方法三:
[root@mongodb ~]#
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/mongodb1.conf
启动 MongoDB 数据库服务器(先启动数据库再进行以下操作)
[root@mongodb ~]# ps aux | grep mongod
查看当前正在运行的所有进程,并筛选出包含 "mongod" 关键字的进程信息
[root@mongodb ~]# kill -9 6779 //杀死进程号
[root@mongodb ~]# netstat -lnpt | grep mongod
[root@mongodb ~]# cd /usr/local/mongodb/conf/
[root@mongodb conf]# cp mongodb{1,2}.conf
用于复制文件。其中,
"mongodb{1,2}.conf"表示匹配两个文件,分别是"mongodb1.conf"和"mongodb2.conf"。通过执行该命令,可以将这两个文件复制到目标位置
[root@mongodb conf]# vim mongodb2.conf(修改红色内容)
port=27018
dbpath=/data/mongodb2
logpath=/data/logs/mongodb/mongodb1.log
logappend=true
fork=true
maxConns=5000
storageEngine=mmapv1
[root@mongodb conf]# mkdir /data/mongodb2
创建MongoDB2目录
[root@mongodb conf]# touch /data/logs/mongodb/mongodb2.log
创建MongoDB2.log文件(同时创建Mongodb1文件然后启动)
[root@mongodb ~]#
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/mongodb2.conf
用于启动 MongoDB 数据库服务器
[root@mongodb ~]# netstat -lnpt | grep mongod
查询当前系统中所有与MongoDB相关的网络连接和对应的进程信息
编写启停脚本
[root@mongodb ~]# vim /etc/init.d/mongodb
#!/bin/bash
INSTANCE=$1
ACTION=$2
case "$ACTION" in
'start')
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/"$INSTANCE".conf;;
'stop')
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/"$INSTANCE".conf --shutdown;;
'restart')
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/"$INSTANCE".conf --shutdown
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/conf/"$INSTANCE".conf;;
esac
[root@mongodb ~]# chmod +x /etc/init.d/mongodb
赋予脚本执行权限
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 stop
停止名为 "mongodb1" 的 MongoDB 服务
[root@mongodb ~]# /etc/init.d/mongodb mongodb2 stop
停止名为 "mongodb2" 的 MongoDB 服务
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 start
开启Mongodb1服务
[root@mongodb ~]# /etc/init.d/mongodb mongodb2 start
开启Mongodb2服务
[root@mongodb ~]# netstat -lnpt | grep mongod
查看mongodb进程
操作 |
作用 |
show dbs |
查看当前示例下的数据库列表,等同于show databases |
show users |
显示用户 |
use |
切换当前数据库 |
db.help() |
显示数据库操作命令 |
show collections |
显示当前数据库中的集合,等同于show tables |
db.table.help() |
显示集合操作命令,table是当前下叫做table的集合 |
db.table.find() |
对当前数据库中table集合进行数据查找 |
数据库(Database)操作
[root@mongodb ~]# mongo
> show dbs
> show databases;
> db
执行 "db" 命令可以显示当前数据库对象或集合
> use admin
运行"use"命令,可以连接到一个指定的数据库
> db
- - 集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表格。
- - 集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
- - 比如,我们可以将以下不同数据结构的文档插入到集合中:
{"site":"www.baidu.com"}
{"site":"www.google.com","name":"Google","age":"30"}
文档(Document)操作
- - 文档是多组键值(key-value)对(即 BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。
- - 一个简单的文档例子如下:
{"site":"www.crushlinux.com", "name":"crushlinux"}
需要注意的是:
文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符
> use local
> show collections
> show tables
> use cloud
> db.user.insert({"id":1,"name":"Crushlinux"}); //创建一个名叫user的集合,写入一个文档
WriteResult({ "nInserted" : 1 })
> show dbs
> show collections
> db.user.find()
> ctrl + d
在终端或命令行界面中,Ctrl + D 通常用于表示输入结束或退出当前会话。当你在终端中输入完命令或文本后,按下Ctrl + D,系统会将输入发送给程序或关闭当前终端会话
[root@mongodb ~]# ll -h /data/mongodb1/cloud.*
用于查看指定路径下的文件或目录的详细信息。具体解释如下:
- `ll`:是`ls -l`的简写,用于显示文件和目录的详细信息。
- `-h`:是`--human-readable`的缩写,用于以人类可读的方式显示文件大小。
- `/data/mongodb1/cloud.*`:是一个文件路径的通配符表达式,表示匹配`/data/mongodb1/`目录下以`cloud.`开头的文件或目录。
综合起来,命令`ll -h /data/mongodb1/cloud.*`的意思是显示`/data/mongodb1/`目录下以`cloud.`开头的文件或目录的详细信息,并以人类可读的方式显示文件大小
如何查看帮助
[root@mongodb ~]# /usr/local/mongodb/bin/mongod --help
用于启动 MongoDB 数据库服务器。`--help` 参数表示显示帮助信息,执行该命令后会显示 MongoDB 的命令行选项和用法说明
[root@mongodb ~]# mongo
> help
> db.help()
> db.version();
> db.stats();
> use cloud
> show collections
> db.user.help()
数据类型
> use study
> db.t1.insert({"id":1});
> show collections
> show dbs
> db
> db.t1.insert({"id":2,"name":"Tom","isadmin":true,"gender":null,"favorite":["apple","banana","orange",1,2,3],"regtime":new Date()});
> db.t1.find()
> db.t1.findOne({'id':2});
> a = db.t1.findOne({"id":2});
> typeof(a.id)
> typeof(a.name)
> typeof(a.isadmin)
> typeof(a.gender)
> typeof(a.favorite)
> typeof(a.regtime)
>db.t1.insert({"id":3,"salary":66666666666666666666666666666,"rx":1.88888888888888888888888});
> db.t1.findOne({"id":3});
> b = db.t1.findOne({"id":3});
> typeof(b.salary)
> typeof(b.rx)
1、数据备份方法
数据导入命令:mongoimport
数据导出导出:mongoexport
备份:
逻辑备份:mongodump
物理备份:冷备份
恢复:mongorestore
2、复制数据库
复制本地数据库:db.copyDatabase(“from_db”,”to_db”,”locolhost”)
复制远程数据库:db.copyDatabase(“from_db”,”to_db”,”192.168.200.101”)
克隆集合:db.runCommand({cloneCollection:”cloud2.t1”,from:”192.168.200.101”})
查看帮助的方法:
[root@mongodb ~]# /usr/local/mongodb/bin/mongoimport --help
[root@mongodb ~]# /usr/local/mongodb/bin/mongoexport --help
[root@mongodb ~]# /usr/local/mongodb/bin/mongodump --help
备份案例
将MySQL数据库内容导入mongodb环境
[root@mongodb ~]# yum -y install mariadb-server mariadb-devel
[root@mongodb ~]# systemctl enable mariadb
[root@mongodb ~]# systemctl start mariadb
[root@mongodb ~]# netstat -lnpt | grep :3306
[root@mongodb ~]# mysql
MariaDB [(none)]> create database cloud;
MariaDB [(none)]> use cloud
MariaDB [cloud]> create table t1(id int,name varchar(20))
MariaDB [cloud]> insert into t1 values(1,"Jack");
MariaDB [cloud]> insert into t1 values(2,"Rose");
MariaDB [cloud]> select * from t1;
导出t1表里的内容到/var/lib/mysql/t1_mysql.csv文件,以“,”逗号分割
MariaDB [cloud]> select * from t1 into outfile '/var/lib/mysql/t1_mysql.csv' fields terminated by ",";
[root@mongodb ~]# cat /var/lib/mysql/t1_mysql.csv
MongoDB复制
将一个数据库实例中的所有数据改变复制到另一个独立的数据库实例的过程,默认是主从复制集群(未来不再使用)。缺点是一旦主库出现故障,需要手动把主库角色切换到最可靠的从库上,而其他从库还需配置从新的主库去同步。
复制的特征
原理上也是MongoDB主从复制技术,但当主库出现故障时,能自动实现主从切换,从而故障得以恢复,其他从库自动从新的主库上同步数据,整个过程不需要手动干预。类似于MySQL中的MHA技术。
主节点记录在其上的所有操作oplog,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。
MongoDB复制结构图如下所示:
以上结构图中,客户端从主节点读取数据,在客户端写入数据到主节点时, 主节点与从节点进行数据交互保障数据的一致性。
复制集的特征
删除之前的实例
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 stop
[root@mongodb ~]# /etc/init.d/mongodb mongodb2 stop
[root@mongodb ~]# rm -rf /data/
配置4个MongoDB实例
[root@mongodb ~]# vim /usr/local/mongodb/conf/mongodb1.conf
port=27017
dbpath=/data/mongodb1
logpath=/data/logs/mongodb/mongodb1.log
logappend=true
fork=true
maxConns=5000
storageEngine=mmapv1
slowms=1
profile=1
replSet=crushlinux //名字随意取(四个实例集群名要一样)
[root@mongodb ~]# vim /usr/local/mongodb/conf/mongodb2.conf
port=27018
dbpath=/data/mongodb2
logpath=/data/logs/mongodb/mongodb2.log
logappend=true
fork=true
maxConns=5000
storageEngine=mmapv1
slowms=1
profile=1
replSet=crushlinux
[root@mongodb ~]# vim /usr/local/mongodb/conf/mongodb3.conf
port=27019
dbpath=/data/mongodb3
logpath=/data/logs/mongodb/mongodb3.log
logappend=true
fork=true
maxConns=5000
storageEngine=mmapv1
slowms=1
profile=1
replSet=crushlinux
[root@mongodb ~]# vim /usr/local/mongodb/conf/mongodb4.conf
port=27020
dbpath=/data/mongodb4
logpath=/data/logs/mongodb/mongodb4.log
logappend=true
fork=true
maxConns=5000
storageEngine=mmapv1
slowms=1
profile=1
replSet=crushlinux
[root@mongodb ~]# mkdir /data/mongodb{1..4} -p
[root@mongodb ~]# mkdir /data/logs/mongodb -p
[root@mongodb ~]# touch /data/logs/mongodb/mongodb{1..4}.log
[root@mongodb ~]# chmod 777 /data/logs/mongodb/mongodb*
[root@mongodb ~]# ll /data/logs/mongodb/mongodb*
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 start
[root@mongodb ~]# /etc/init.d/mongodb mongodb2 start
[root@mongodb ~]# /etc/init.d/mongodb mongodb3 start
[root@mongodb ~]# /etc/init.d/mongodb mongodb4 start
[root@mongodb ~]# netstat -lnpt | grep mongod
[root@mongodb ~]# mongo
111:PRIMARY> rs.help() //查看复制集帮助指令
> rs.status()
>
cfg={"_id":"crushlinux","members":[{"_id":0,"host":"127.0.0.1:27017"},{"_id":1,"host":"127.0.0.1:27018"},{"_id":2,"host":"127.0.0.1:27019"}]}
> rs.initiate(cfg)
111x:PRIMARY> rs.status()
crushlinux:PRIMARY> rs.status() 【里面的信息】
{
"set" : "crushlinux",
"date" : ISODate("2020-01-07T08:41:04.997Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1578386452, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1578386452, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1578386452, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1578386452, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",
"health" : 1, //1为健康,0为宕机
"state" : 1, //1为主,2为从
"stateStr" : "PRIMARY",
"uptime" : 125,
"optime" : {
"ts" : Timestamp(1578386452, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-07T08:40:52Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1578386449, 1),
"electionDate" : ISODate("2020-01-07T08:40:49Z"),
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 26,
"optime" : {
"ts" : Timestamp(1578386452, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1578386452, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-07T08:40:52Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:40:52Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:41:03.888Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:41:04.492Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:27017",
"syncSourceHost" : "127.0.0.1:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 26,
"optime" : {
"ts" : Timestamp(1578386452, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1578386452, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-07T08:40:52Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:40:52Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:41:03.888Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:41:04.441Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:27017",
"syncSourceHost" : "127.0.0.1:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1578386452, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578386452, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
crushlinux:PRIMARY> rs.add("127.0.0.1:27020") //增加一个节点
{
"ok" : 1,
"operationTime" : Timestamp(1578386643, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578386643, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
crushlinux:PRIMARY> rs.status()
{
"set" : "crushlinux",
"date" : ISODate("2020-01-07T08:44:25.733Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 326,
"optime" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-07T08:44:21Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1578386449, 1),
"electionDate" : ISODate("2020-01-07T08:40:49Z"),
"configVersion" : 2,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 227,
"optime" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-07T08:44:21Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:44:21Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:44:25.210Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:44:24.254Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:27020",
"syncSourceHost" : "127.0.0.1:27020",
"syncSourceId" : 3,
"infoMessage" : "",
"configVersion" : 2
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 227,
"optime" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-07T08:44:21Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:44:21Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:44:25.210Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:44:24.255Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:27020",
"syncSourceHost" : "127.0.0.1:27020",
"syncSourceId" : 3,
"infoMessage" : "",
"configVersion" : 2
},
{
"_id" : 3,
"name" : "127.0.0.1:27020",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 22,
"optime" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1578386661, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-01-07T08:44:21Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:44:21Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:44:25.229Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:44:25.732Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:27017",
"syncSourceHost" : "127.0.0.1:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 2
}
],
"ok" : 1,
"operationTime" : Timestamp(1578386661, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578386661, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
crushlinux:PRIMARY> rs.remove("127.0.0.1:27020") //删除节点
{
"ok" : 1,
"operationTime" : Timestamp(1578386690, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578386690, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
[root@mongodb ~]# ps aux | grep mongod
[root@mongodb ~]# kill -9 67461 //模拟故障
[root@mongodb ~]# mongo --port 27018
.0{
"set" : "crushlinux",
"date" : ISODate("2020-01-07T08:47:01.674Z"),
"myState" : 1,
"term" : NumberLong(2),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1578386816, 1),
"t" : NumberLong(2)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1578386816, 1),
"t" : NumberLong(2)
},
"appliedOpTime" : {
"ts" : Timestamp(1578386816, 1),
"t" : NumberLong(2)
},
"durableOpTime" : {
"ts" : Timestamp(1578386816, 1),
"t" : NumberLong(2)
}
},
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDurable" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:47:01.427Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:46:45.095Z"),
"pingMs" : NumberLong(1),
"lastHeartbeatMessage" : "Error connecting to 127.0.0.1:27017 :: caused by :: Connection refused",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : -1
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 478,
"optime" : {
"ts" : Timestamp(1578386816, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2020-01-07T08:46:56Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1578386815, 1),
"electionDate" : ISODate("2020-01-07T08:46:55Z"),
"configVersion" : 3,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 381,
"optime" : {
"ts" : Timestamp(1578386816, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1578386816, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2020-01-07T08:46:56Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:46:56Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:47:01.421Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:47:01.588Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:27018",
"syncSourceHost" : "127.0.0.1:27018",
"syncSourceId" : 1,
"infoMessage" : "",
"configVersion" : 3
}
],
"ok" : 1,
"operationTime" : Timestamp(1578386816, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578386816, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 start
about to fork child process, waiting until server is ready for connections.
forked process: 67927
child process started successfully, parent exiting
[root@mongodb ~]# mongo --port 27018
crushlinux:PRIMARY> rs.status()
{
"set" : "crushlinux",
"date" : ISODate("2020-01-07T08:48:37.546Z"),
"myState" : 1,
"term" : NumberLong(2),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1578386916, 1),
"t" : NumberLong(2)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1578386916, 1),
"t" : NumberLong(2)
},
"appliedOpTime" : {
"ts" : Timestamp(1578386916, 1),
"t" : NumberLong(2)
},
"durableOpTime" : {
"ts" : Timestamp(1578386916, 1),
"t" : NumberLong(2)
}
},
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 29,
"optime" : {
"ts" : Timestamp(1578386906, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1578386906, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2020-01-07T08:48:26Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:48:26Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:48:35.591Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:48:36.200Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:27019",
"syncSourceHost" : "127.0.0.1:27019",
"syncSourceId" : 2,
"infoMessage" : "",
"configVersion" : 3
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 574,
"optime" : {
"ts" : Timestamp(1578386916, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2020-01-07T08:48:36Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1578386815, 1),
"electionDate" : ISODate("2020-01-07T08:46:55Z"),
"configVersion" : 3,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 477,
"optime" : {
"ts" : Timestamp(1578386916, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1578386916, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2020-01-07T08:48:36Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:48:36Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:48:37.544Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:48:35.755Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:27018",
"syncSourceHost" : "127.0.0.1:27018",
"syncSourceId" : 1,
"infoMessage" : "",
"configVersion" : 3
}
],
"ok" : 1,
"operationTime" : Timestamp(1578386916, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578386916, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
手动切换主实例
[root@mongodb ~]# mongo --port 27018
crushlinux:PRIMARY> rs.help() //查看帮助
crushlinux:PRIMARY> rs.freeze(30) //暂停30秒不参加选举
{
"operationTime" : Timestamp(1578387047, 1),
"ok" : 0,
"errmsg" : "cannot freeze node when primary or running for elec
tion. state: Primary", "code" : 95,
"codeName" : "NotSecondary",
"$clusterTime" : {
"clusterTime" : Timestamp(1578387047, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0)
}
}
}
crushlinux:PRIMARY> rs.stepDown(60,30) //修改成从节点
2020-01-07T16:51:20.451+0800 E QUERY [js] Error: error doing query: failed: network error while attempting to run command 'replSetStepDown' o
n host '127.0.0.1:27018' :DB.prototype.runCommand@src/mongo/shell/db.js:168:1
DB.prototype.adminCommand@src/mongo/shell/db.js:186:16
rs.stepDown@src/mongo/shell/utils.js:1444:12
@(shell):1:1
2020-01-07T16:51:20.458+0800 I NETWORK [js] trying reconnect to 127.0.0.1:27018 failed
2020-01-07T16:51:20.459+0800 I NETWORK [js] reconnect 127.0.0.1:27018 ok
crushlinux:SECONDARY> rs.status()
{
"set" : "crushlinux",
"date" : ISODate("2020-01-07T08:52:23.684Z"),
"myState" : 2,
"term" : NumberLong(3),
"syncingTo" : "127.0.0.1:27017",
"syncSourceHost" : "127.0.0.1:27017",
"syncSourceId" : 0,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1578387142, 1),
"t" : NumberLong(3)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1578387142, 1),
"t" : NumberLong(3)
},
"appliedOpTime" : {
"ts" : Timestamp(1578387142, 1),
"t" : NumberLong(3)
},
"durableOpTime" : {
"ts" : Timestamp(1578387142, 1),
"t" : NumberLong(3)
}
},
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 256,
"optime" : {
"ts" : Timestamp(1578387142, 1),
"t" : NumberLong(3)
},
"optimeDurable" : {
"ts" : Timestamp(1578387142, 1),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2020-01-07T08:52:22Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:52:22Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:52:23.611Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:52:22.601Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1578387080, 1),
"electionDate" : ISODate("2020-01-07T08:51:20Z"),
"configVersion" : 3
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 800,
"optime" : {
"ts" : Timestamp(1578387142, 1),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2020-01-07T08:52:22Z"),
"syncingTo" : "127.0.0.1:27017",
"syncSourceHost" : "127.0.0.1:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 3,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 703,
"optime" : {
"ts" : Timestamp(1578387142, 1),
"t" : NumberLong(3)
},
"optimeDurable" : {
"ts" : Timestamp(1578387142, 1),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2020-01-07T08:52:22Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:52:22Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:52:23.428Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:52:23.252Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "127.0.0.1:27017",
"syncSourceHost" : "127.0.0.1:27017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 3
}
],
"ok" : 1,
"operationTime" : Timestamp(1578387142, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578387142, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
[root@mongodb ~]# /etc/init.d/mongodb mongodb1 stop
killing process with pid: 67927
当模拟mongodb1实例故障时,由于mongodb2实例不参与选举,因此mongodb3也就是27019将会成为新的主节点
crushlinux:SECONDARY> rs.status()
{
"set" : "crushlinux",
"date" : ISODate("2020-01-07T08:53:50.785Z"),
"myState" : 2,
"term" : NumberLong(4),
"syncingTo" : "127.0.0.1:27019",
"syncSourceHost" : "127.0.0.1:27019",
"syncSourceId" : 2,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1578387221, 1),
"t" : NumberLong(4)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1578387221, 1),
"t" : NumberLong(4)
},
"appliedOpTime" : {
"ts" : Timestamp(1578387221, 1),
"t" : NumberLong(4)
},
"durableOpTime" : {
"ts" : Timestamp(1578387221, 1),
"t" : NumberLong(4)
}
},
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:27017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDurable" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:53:50.107Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:53:10.770Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "Error connecting to 127.0.0.1:27017 :: caused by :: Connection refused",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : -1
},
{
"_id" : 1,
"name" : "127.0.0.1:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 887,
"optime" : {
"ts" : Timestamp(1578387221, 1),
"t" : NumberLong(4)
},
"optimeDate" : ISODate("2020-01-07T08:53:41Z"),
"syncingTo" : "127.0.0.1:27019",
"syncSourceHost" : "127.0.0.1:27019",
"syncSourceId" : 2,
"infoMessage" : "",
"configVersion" : 3,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 2,
"name" : "127.0.0.1:27019",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 790,
"optime" : {
"ts" : Timestamp(1578387221, 1),
"t" : NumberLong(4)
},
"optimeDurable" : {
"ts" : Timestamp(1578387221, 1),
"t" : NumberLong(4)
},
"optimeDate" : ISODate("2020-01-07T08:53:41Z"),
"optimeDurableDate" : ISODate("2020-01-07T08:53:41Z"),
"lastHeartbeat" : ISODate("2020-01-07T08:53:50.068Z"),
"lastHeartbeatRecv" : ISODate("2020-01-07T08:53:49.674Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1578387199, 1),
"electionDate" : ISODate("2020-01-07T08:53:19Z"),
"configVersion" : 3
}
],
"ok" : 1,
"operationTime" : Timestamp(1578387221, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1578387221, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
1、复制的原理
MongoDB复制是基于操作日志oplog实现,oplog相当于mysql中的二进制日志,只记录数据发生的改变操作。
2、选举的原理
(1)节点类型:标准节点,被动节点,仲裁节点
(2)标准节点与被动节点的区别
priority值高者是标准节点,低者则为被动节点
(3)选举规则
票数高者获胜,priority是优先权0-1000值,相当于额外增加0-1000的票数。
选举结果:票数高者获胜;若票数相同,数据新者获胜。