Mongodb主从架构
主从复制原理
MongoDB Oplog是MongoDB Primary和Secondary在复制建立期间和建立完成之后的复制介质,就是Primary中所有的写入操作都会记录到MongoDB Oplog中,然后从库会来主库一直拉取Oplog并应用到自己的数据库中。
Oplog是MongoDB local数据库的一个集合,它是Capped collection,通俗意思就是它是固定大小,循环使用的。
-
对于Mongodb来说,并不推荐使用Master-Slave架构,因为Master-Slave其中Master宕机后不能自动恢复
-
Master-Slave不支持链式结构,Slave只能直接连接Master(Redis的Master-Slave支持链式结构,Slave可以连接Slave,成为Slave的Slave。)
主从部署方案
主从配置高可用方案搭建过程(此高可用方案不推荐使用,只做参考):
1 mongodb安装
参照压缩包下载安装法
2 创建mongodb数据存储与日志存储目录
mkdir /var/mongo-ms/master/data -p
mkdir /var/mongo-ms/master/logs -p
mkdir /var/mongo-ms/slave/data -p
mkdir /var/mongo-ms/slave/data -p
-
主从部署的数据与日志统一存放在 /var/mongo-ms目录下
-
master代表主结点存放的数据与日志文件夹
-
slave代表从结点存放的数据与日志文件夹
3 创建mongodb配置文件
- 新增主结点配置文件mongodb.cfg
mongodb.cfg 存放在/var/mongo-ms/master 目录下
vi /var/mongo-ms/master/mongodb.cfg
进入vi编辑界面,配置以下信息
#数据库文件位置
dbpath=/var/mongo-ms/master/data
#日志文件位置
logpath=/var/mongo-ms/master/logs/mongo.log
#以追加方式写入日志
logappend=true
#是否以守护进程方式运行
fork=true
#绑定客户端访问的ip, 0.0.0.0表示不绑定ip
bind_ip=0.0.0.0
#配置客户端访问的端口号,默认端口号27017
port=27000
#开启用于数据故障恢复(journal会另外使用一块内存区域,journal一般默认100ms刷新一次,它以日志方式来记录)和持久化数据
#对于数据比较重要的建议开启,数据不重要的不建议开启(因为会使用更多内存)
#journal=true
#确定自己是主服务器
master=true
编辑完成后,保存。
- 新增从结点配置文件mongodb.cfg
mongodb.cfg 存放在/var/mongo-ms/master 目录下
vi /var/mongo-ms/master/mongodb.cfg
进入vi编辑界面,配置以下信息
#数据库文件位置
dbpath=/var/mongo-ms/slave/data
#日志文件位置
logpath=/var/mongo-ms/slave/logs/mongo.log
#以追加方式写入日志
logappend=true
#是否以守护进程方式运行
fork=true
#绑定客户端访问的ip 0.0.0.0 不绑定ip
bind_ip=0.0.0.0
#配置客户端访问的端口号,默认端口号27017
port=27011
#确定主数据库端口
source=192.168.239.210:27010
#确定自己是从服务器
slave=true
#开启用于数据故障恢复(journal会另外使用一块内存区域,journal一般默认100ms刷新一次,它以日志方式来记录)和持久化数据
#对于数据比较重要的建议开启,数据不重要的不建议开启(因为会使用更多内存)
#journal=true
source=192.168.239.210:27010 本机IP为192.168.239.210
slave=true 标识该结点为从结点
编辑完成后,保存。
4 启动服务
- 启动主结点服务和从结点服务
[root@localhost ~]# mongod -f /var/mongo-ms/master/mongodb.cfg
about to fork child process, waiting until server is ready for connections.
forked process: 2778
child process started successfully, parent exiting
[root@localhost ~]# mongod -f /var/mongo-ms/slave/mongodb.cfg
about to fork child process, waiting until server is ready for connections.
forked process: 2843
child process started successfully, parent exiting
注:mongo命令直接使用的话,需要设置环境变量(环境变更设置自行百度)
没有设置环境变量的话
可进入对应的/bin目录后,再执行以上命令;
或者用绝对路径 : /var/mongo-ms/master/bin/mongo -f /var/mongo-ms/master/mongodb.cfg
5 查看是否启动成功
[root@localhost ~]# ps aux|grep mongo
root 2778 1.4 3.9 1065876 74052 ? Sl 22:55 0:06 mongod -f /var/mongo-ms/master/mongodb.cfg
root 2843 2.6 4.4 1031028 82520 ? Sl 23:01 0:03 mongod -f /var/mongo-ms/slave/mongodb.cfg
root 2881 0.0 0.0 112660 968 pts/0 S+ 23:03 0:00 grep --color=auto mongo
进程 2778,2843分别为对应mongodb的主结点服务和从结点服务进程
6 主从复制测试
mongodb主结点服务端口号为27010,从结点端口号为27011
SSH会话A
- 打开一个ssh会话A ,连接主结点mongodb服务
[root@localhost ~]# mongo 127.0.0.1:27010
MongoDB shell version v3.6.11
connecting to: mongodb://127.0.0.1:27010/test?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("db291dc2-fbfb-4f21-b1ea-2ebb6d5aa732") }
MongoDB server version: 3.6.11
Server has startup warnings:
2021-06-29T22:55:39.870+0800 I CONTROL [initandlisten]
2021-06-29T22:55:39.870+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2021-06-29T22:55:39.870+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2021-06-29T22:55:39.871+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2021-06-29T22:55:39.871+0800 I CONTROL [initandlisten]
2021-06-29T22:55:39.872+0800 I CONTROL [initandlisten]
2021-06-29T22:55:39.872+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2021-06-29T22:55:39.872+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2021-06-29T22:55:39.872+0800 I CONTROL [initandlisten]
2021-06-29T22:55:39.873+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2021-06-29T22:55:39.873+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2021-06-29T22:55:39.873+0800 I CONTROL [initandlisten]
2021-06-29T22:55:39.873+0800 I CONTROL [initandlisten] ** WARNING: This node was started in master-slave replication mode.
2021-06-29T22:55:39.873+0800 I CONTROL [initandlisten] ** Master-slave replication is deprecated and subject to be removed
2021-06-29T22:55:39.873+0800 I CONTROL [initandlisten] ** in a future version.
2021-06-29T22:55:39.873+0800 I CONTROL [initandlisten]
>
- 查看是否是主结点
> db.isMaster()
{
"ismaster" : true,
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 100000,
"localTime" : ISODate("2021-06-29T14:58:11.819Z"),
"logicalSessionTimeoutMinutes" : 30,
"minWireVersion" : 0,
"maxWireVersion" : 6,
"readOnly" : false,
"ok" : 1
}
“readOnly” : false 主结点,不是只读的
- 创建数据库 eijiyey
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
>
> use eijiyey
switched to db eijiyey
- 创建数据集并插入数据
> db.order.insert({"id":1,"orderNo":"001"})
WriteResult({ "nInserted" : 1 })
> db.order.find()
{ "_id" : ObjectId("60db3919d8df8dcc51e009a6"), "id" : 1, "orderNo" : "001" }
>
SSH会话B
打开一个ssh会话B ,连接从结点mongodb服务
mongo 127.0.0.1:27011
成功进入mongodb命令行
> show dbs
2021-06-29T23:19:02.064+0800 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:67:1
shellHelper.show@src/mongo/shell/utils.js:860:19
shellHelper@src/mongo/shell/utils.js:750:15
@(shellhelp2):1:1
"errmsg" : “not master and slaveOk=false”, 该结点不是master结点 ,或者slaveOk状态为false。表示不可读写
- 从结点只读设置 - 临时生效
slaveOk可读设置,临时生效,只需要在mongodb客户端连接的命令行会话中执行发下命令即可
> rs.slaveOk()
> show dbs
admin 0.000GB
config 0.000GB
eijiyey 0.000GB
local 0.000GB
> db.order.find()
{ "_id" : ObjectId("60db3803d8df8dcc51e009a5"), "id" : 1, "orderNo" : "001" }
>
- 从结点只读设置 - 永久生效
在安装了mongodb的服务器中查找到 .mongorc.js 文件(一般这个文件都是空的),在文件里面添加一行:rs.slaveOk();
[root@localhost ~]# find / -name .mongorc.js
/root/.mongorc.js
[root@localhost ~]# vi /root/.mongorc.js
rs.slaveOk();
".mongorc.js" 1L, 14C written
[root@localhost ~]# mongo 127.0.0.1:27011
> show dbs
admin 0.000GB
config 0.000GB
eijiyey 0.000GB
local 0.000GB
> db.order.find()
{ "_id" : ObjectId("60db3803d8df8dcc51e009a5"), "id" : 1, "orderNo" : "001" }
>
从以上结果可以看出,master中的eijiyey库及下数据已全部复制到slave中
7 从结点只读测试
连接进入slave结点客户端,查询数据,新增一条数据,结果如下
> use eijiyey
switched to db eijiyey
> db.order.find()
{ "_id" : ObjectId("60db3919d8df8dcc51e009a6"), "id" : 1, "orderNo" : "001" }
> db.order.insert({"id":2,"orderNo":"002"})
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })
>
从以上结果可以看出,可读不可写。
“errmsg” : “not master” ,不是master结点,不可写。
8 从结点不会自动切换为主结点测试
- 关闭master结点服务
[root@localhost ~]# ps aux|grep mongo
root 2778 1.0 4.7 1068036 88612 ? Sl 6月29 0:40 mongod -f /var/mongo-ms/master/mongodb.cfg
root 2843 1.1 4.5 1032056 84516 ? Sl 6月29 0:39 mongod -f /var/mongo-ms/slave/mongodb.cfg
root 2898 0.0 1.4 781844 27064 pts/0 Sl+ 6月29 0:00 mongo 127.0.0.1:27010
root 2974 0.0 0.0 112656 972 pts/1 S+ 00:00 0:00 grep --color=auto mongo
[root@localhost ~]# kill 2778
[root@localhost ~]# ps aux|grep mongo
root 2843 1.1 4.5 1032056 84516 ? Sl 6月29 0:39 mongod -f /var/mongo-ms/slave/mongodb.cfg
root 2898 0.0 1.4 781844 27064 pts/0 Sl+ 6月29 0:00 mongo 127.0.0.1:27010
root 2997 0.0 0.0 112656 968 pts/1 S+ 00:01 0:00 grep --color=auto mongo
[root@localhost ~]#
- 进入slave客户端并查看结点状态
[root@localhost ~]# mongo 127.0.0.1:27011
> rs.isMaster()
{
"ismaster" : false,
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 100000,
"localTime" : ISODate("2021-06-29T16:02:31.067Z"),
"logicalSessionTimeoutMinutes" : 30,
"minWireVersion" : 0,
"maxWireVersion" : 6,
"readOnly" : false,
"ok" : 1
}
“ismaster” : false 此处可以看出,该结点依然是从结点,而没有自动切换为主结点