MongoDB是一个开源,跨平台,面向文档的数据库管理系统。MongoDB是NoSQL(不仅是SQL)数据库软件。MongoDB使用带有模式的文档之类的JSON(JavaScript对象表示法)。MongoDB由MongoDB Inc开发,并根据SSPL(服务器端公共许可证)进行分发。
MongoDB集群类型
一般来说,MongoDB集群有如下3种安装方式:
其中第1种主从模式官网也不再推荐上生产环境,主要是安全性太低。
副本集和sharding模式目前是用的最广的方案,通常这2种方案的选择通过数据量和并发数来权衡。在GB级别的基本上副本集方案可满足,TB级别或以上采用sharding模式,解决单机容量和单机并发能力。
这两种既有自己的优势也有自己的缺点,比如sharding模式分片越多,性能自然下降越多。
Replica Set(副本集)说明:
副本集,是指集群当中拥有多份节点数据,一旦主节点挂掉,其他备节点能够根据仲裁节点选举出一个主节点,继续提供数据服务,以保证集群的高可用,该机制的需要副本数据与主节点保持一致。
Master表示主节点,Slaver表示备节点,Arbiter表示仲裁节点。主备节点存储数据,仲裁节点不存储数据。客户端同时连接主节点与备节点,不连接仲裁节点。
默认设置下,主节点提供所有增删查改服务,备节点不提供任何服务。但是可以通过设置使备节点提供查询服务,这样就可以减少主节点的压力,当客户端进行数据查询时,请求自动转到备节点上。这个设置叫做Read Preference Modes,同时Java客户端提供了简单的配置方式,可以不必直接对数据库进行操作。
仲裁节点是一种特殊的节点,它本身并不存储数据,主要的作用是决定哪一个备节点在主节点挂掉之后提升为主节点,所以客户端不需要连接此节点。这里虽然只有一个备节点,但是仍然需要一个仲裁节点来提升备节点级别。我开始也不相信必须要有仲裁节点,但是自己也试过没仲裁节点的话,主节点挂了备节点还是备节点,所以咱们还是需要它的。
环境参数
操作系统: CentOS 7
MongoDB版本: 4.0.26
服务器规划
3台服务器来安装Replica Set方式的集群
:
服务器 | 端口 | 配置 | 节点作用 |
---|---|---|---|
111.111.111.111 | 40001 | 4C32G | Primary主节点(M) |
111.111.111.112 | 40002 | 4C32G | Secondary从节点 (S) |
111.111.111.113 | 40003 | 4C32G | Arbiter仲裁节点(A) |
先在官网下载mongodb文件,这里使用4.0.26版本(注意:版本号中的第二个数如果为奇数则为开发版、偶数为稳定版),这里我解压到 /data 目录下, 并重命名为 mongodb4-rs-version。
1、设置配置文件:
Mongodb Primary主节点(M): testrs_40001.yaml
systemLog:
#MongoDB发送所有日志输出的目录指定为文件
destination: file
#指定日志路径
path: /data/mongodb4-rs-version/log/testrs.log
logAppend: true
storage:
# 存储数据库的数据目录
dbPath: /data/mongodb4-rs-version/data/db/testrs
# 启用和禁用持久性日志以确保数据文件保持有效和数据恢复
journal:
enabled: true
processManagement:
# 支持后台启动
fork: true
# 记录进程id
pidFilePath: /data/mongodb4-rs-version/pid/testrs.pid
net:
# 设置绑定ip地址
bindIp: 111.111.111.111
# 绑定端口
port: 40001
setParameter:
# 认证设置
enableLocalhostAuthBypass: false
# 副本集名称
replication:
replSetName: testrs
#security:
# keyFile: /data/mongodb4-rs-version/secret_key/keyFile
# authorization: enabled
其他2个节点类似,替换IP + Port部分:
Mongodb Secondary从节点 (S):testrs_40002.yaml
net:
# 设置绑定ip地址
bindIp: 111.111.111.112
# 绑定端口
port: 40002
Mongodb Arbiter仲裁节点(A):testrs_40003.yaml
net:
# 设置绑定ip地址
bindIp: 111.111.111.113
# 绑定端口
port: 40003
2、三台服务器上依次创建如下文件夹
mkdir -p /data/mongodb4-rs-version/{data,log,pid,mycfg,secret_key}
mkdir -p /data/mongodb4-rs-version/data/db/testrs
目录结构:
[root@dn3 data]# tree mongodb4-rs-version/
mongodb4-rs-version/
├── bin
│ ├── bsondump
│ ├── install_compass
│ ├── mongo
│ ├── mongod
│ ├── mongodump
│ ├── mongoexport
│ ├── mongofiles
│ ├── mongoimport
│ ├── mongoreplay
│ ├── mongorestore
│ ├── mongos
│ ├── mongostat
│ └── mongotop
├── data
│ └── db
│ └── testrs
│ ├── collection-0-2001569133389284182.wt
│ ├── collection-0-6977138810631015761.wt
│ ├── collection-10-2001569133389284182.wt
│ ├── collection-11-2001569133389284182.wt
│ ├── collection-13-2001569133389284182.wt
│ ├── collection-15-2001569133389284182.wt
│ ├── collection-17-2001569133389284182.wt
│ ├── collection-19-2001569133389284182.wt
│ ├── collection-21-2001569133389284182.wt
│ ├── collection-2-2001569133389284182.wt
│ ├── collection-24-2001569133389284182.wt
│ ├── collection-26-2001569133389284182.wt
│ ├── collection-28-2001569133389284182.wt
│ ├── collection-4-2001569133389284182.wt
│ ├── collection-6-2001569133389284182.wt
│ ├── collection-8-2001569133389284182.wt
│ ├── diagnostic.data
│ │ ├── metrics.2022-04-21T08-53-57Z-00000
│ │ ├── metrics.2022-04-21T13-26-06Z-00000
│ │ ├── metrics.2022-04-21T14-18-53Z-00000
│ │ ├── metrics.2022-04-21T15-26-04Z-00000
│ │ ├── metrics.2022-04-21T15-31-32Z-00000
│ │ ├── metrics.2022-04-22T11-09-44Z-00000
│ │ ├── metrics.2022-04-22T14-01-56Z-00000
│ │ └── metrics.interim
│ ├── index-1-2001569133389284182.wt
│ ├── index-12-2001569133389284182.wt
│ ├── index-14-2001569133389284182.wt
│ ├── index-16-2001569133389284182.wt
│ ├── index-1-6977138810631015761.wt
│ ├── index-18-2001569133389284182.wt
│ ├── index-20-2001569133389284182.wt
│ ├── index-22-2001569133389284182.wt
│ ├── index-23-2001569133389284182.wt
│ ├── index-25-2001569133389284182.wt
│ ├── index-2-6977138810631015761.wt
│ ├── index-27-2001569133389284182.wt
│ ├── index-29-2001569133389284182.wt
│ ├── index-3-2001569133389284182.wt
│ ├── index-5-2001569133389284182.wt
│ ├── index-7-2001569133389284182.wt
│ ├── index-9-2001569133389284182.wt
│ ├── journal
│ │ ├── WiredTigerLog.0000000007
│ │ ├── WiredTigerPreplog.0000000001
│ │ └── WiredTigerPreplog.0000000002
│ ├── _mdb_catalog.wt
│ ├── mongod.lock
│ ├── sizeStorer.wt
│ ├── storage.bson
│ ├── WiredTiger
│ ├── WiredTigerLAS.wt
│ ├── WiredTiger.lock
│ ├── WiredTiger.turtle
│ └── WiredTiger.wt
├── LICENSE-Community.txt
├── log
│ └── testrs.log
├── MPL-2
├── mycfg
│ └── testrs_40001.yaml
├── pid
│ └── testrs.pid
├── README
├── secret_key
│ └── keyFile
├── THIRD-PARTY-NOTICES
└── THIRD-PARTY-NOTICES.gotools
10 directories, 75 files
3、启动服务:
[root@dn3 mycfg]# /data/mongodb4-rs-version/bin/mongod -f /data/mongodb4-rs-version/mycfg/testrs_40001.yaml
[root@dn4 mycfg]# /data/mongodb4-rs-version/bin/mongod -f /data/mongodb4-rs-version/mycfg/testrs_40002.yaml
[root@dn5 mycfg]# /data/mongodb4-rs-version/bin/mongod -f /data/mongodb4-rs-version/mycfg/testrs_40003.yaml
4、查看服务情况:
[root@dn3 mycfg]# ps -ef|grep mongo
[root@dn4 mycfg]# ps -ef|grep mongo
[root@dn5 mycfg]# ps -ef|grep mongo
5、选择主节点接入Mongo集群
[root@dn5 mongodb4-rs-version]# /opt/mongodb4.0.26/bin/mongo 111.111.111.111:40001
MongoDB shell version v4.0.26
connecting to: mongodb://111.111.111.111:40001/test?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("021e9bc9-a348-4520-9ae5-77ecb2d1c208") }
MongoDB server version: 4.0.26
Server has startup warnings:
2022-04-21T16:53:57.229+0800 I STORAGE [initandlisten]
2022-04-21T16:53:57.229+0800 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2022-04-21T16:53:57.229+0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem
2022-04-21T16:53:57.797+0800 I CONTROL [initandlisten]
2022-04-21T16:53:57.797+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2022-04-21T16:53:57.797+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2022-04-21T16:53:57.797+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended.
2022-04-21T16:53:57.797+0800 I CONTROL [initandlisten]
---
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).
The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.
To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
6、初始化集群副本集
# 执行initiate的节点将成为Master节点
> rs.initiate()
{
"info2" : "no configuration specified. Using a default configuration for the set",
"me" : "111.111.111.111:40001",
"ok" : 1
}
7、加入从节点(副本节点)
# 通过add加入的节点默认为Slaver节点, 但如果Master节点意外退出, 几个副本节点中的一个有机会通过仲裁节点选举成为主节点
testrs:SECONDARY> rs.add("111.111.111.112:40002")
{
"ok" : 1,
"operationTime" : Timestamp(1650531631, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1650531631, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
8、加入仲裁节点
testrs:PRIMARY> rs.addArb("111.111.111.113:40003")
{
"ok" : 1,
"operationTime" : Timestamp(1650531727, 2),
"$clusterTime" : {
"clusterTime" : Timestamp(1650531727, 2),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
9、查看集群配置
testrs:PRIMARY> rs.conf()
{
"_id" : "testrs",
"version" : 3,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "111.111.111.111:40001",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "111.111.111.112:40002",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "111.111.111.113:40003",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : -1,
"catchUpTakeoverDelayMillis" : 30000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("62611cef03d51d144b7e70e0")
}
}
10、查看集群状态
testrs:PRIMARY> rs.status()
{
"set" : "testrs",
"date" : ISODate("2022-04-21T09:09:03.679Z"),
"myState" : 1,
"term" : NumberLong(1),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1650532137, 1),
"t" : NumberLong(1)
},
"readConcernMajorityOpTime" : {
"ts" : Timestamp(1650532137, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1650532137, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1650532137, 1),
"t" : NumberLong(1)
}
},
"lastStableCheckpointTimestamp" : Timestamp(1650532107, 1),
"electionCandidateMetrics" : {
"lastElectionReason" : "electionTimeout",
"lastElectionDate" : ISODate("2022-04-21T08:59:27.299Z"),
"electionTerm" : NumberLong(1),
"lastCommittedOpTimeAtElection" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"lastSeenOpTimeAtElection" : {
"ts" : Timestamp(1650531567, 1),
"t" : NumberLong(-1)
},
"numVotesNeeded" : 1,
"priorityAtElection" : 1,
"electionTimeoutMillis" : NumberLong(10000),
"newTermStartDate" : ISODate("2022-04-21T08:59:27.300Z"),
"wMajorityWriteAvailabilityDate" : ISODate("2022-04-21T08:59:27.340Z")
},
"members" : [
{
"_id" : 0,
"name" : "111.111.111.111:40001",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 906,
"optime" : {
"ts" : Timestamp(1650532137, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-04-21T09:08:57Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"electionTime" : Timestamp(1650531567, 2),
"electionDate" : ISODate("2022-04-21T08:59:27Z"),
"configVersion" : 3,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 1,
"name" : "111.111.111.112:40002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 512,
"optime" : {
"ts" : Timestamp(1650532137, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1650532137, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2022-04-21T09:08:57Z"),
"optimeDurableDate" : ISODate("2022-04-21T09:08:57Z"),
"lastHeartbeat" : ISODate("2022-04-21T09:09:02.431Z"),
"lastHeartbeatRecv" : ISODate("2022-04-21T09:09:02.618Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "111.111.111.111:40001",
"syncSourceHost" : "111.111.111.111:40001",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 3
},
{
"_id" : 2,
"name" : "111.111.111.111:40003",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 415,
"lastHeartbeat" : ISODate("2022-04-21T09:09:02.404Z"),
"lastHeartbeatRecv" : ISODate("2022-04-21T09:09:02.205Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 3
}
],
"ok" : 1,
"operationTime" : Timestamp(1650532137, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1650532137, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
11、 删除集群节点测试(仲裁节点)
testrs:PRIMARY> rs.remove("111.111.111.113:40003")
{
"ok" : 1,
"operationTime" : Timestamp(1650532578, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1650532578, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
12、 测试在从节点
上进入集群并插入数据
[root@dn4 mongodb4-rs-version]# /data/mongodb4-rs-version/bin/mongo 111.111.111.112:40002
testrs:SECONDARY> use test1
switched to db test1
testrs:SECONDARY> show dbs
2022-04-21T17:25:21.544+0800 E QUERY [js] Error: listDatabases failed:{
"operationTime" : Timestamp(1650533117, 1),
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk",
"$clusterTime" : {
"clusterTime" : Timestamp(1650533117, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:151:1
shellHelper.show@src/mongo/shell/utils.js:882:13
shellHelper@src/mongo/shell/utils.js:766:15
@(shellhelp2):1:1
testrs:SECONDARY> 输入exit
bye
13、显式设置该登录节点为从节点
由11步的报错中可以看到, 如果该节点不是从节点, 则不允许插入数据
执行显式设置从节点可以使用
rs.secondaryOk()
命令, 如下命令随着版本的升级迭代, 已废弃.
- rs.slaveOk() 或者 rs.slaveOk(true)
# 把 111.111.111.112 节点显式设置为从节点
testrs:SECONDARY> rs.secondaryOk()
testrs:SECONDARY> use test1
switched to db test1
testrs:SECONDARY> db
test1
testrs:SECONDARY> db.test1.insert({"name":"Andy"})
WriteCommandError({
"operationTime" : Timestamp(1650533977, 1),
"ok" : 0,
"errmsg" : "not master",
"code" : 10107,
"codeName" : "NotMaster",
"$clusterTime" : {
"clusterTime" : Timestamp(1650533977, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
})
1、集群 keyFile 认证-生成密钥文件
openssl rand -base64 90 > keyfile
2、该key的权限必须是600
MongoDB的keyFile要求仅自身拥有权限,同组或其他组不能拥有权限
chmod 600 /keyfile所在的目录/keyfile
3、在配置文件中testrs_40001.yaml、testrs_40002.yaml、testrs_40003.yaml 都添加:
security:
keyFile: /keyfile所在的目录/keyfile
authorization: enabled
4、启动mongo服务,添加管理员可以操作复制集的权限(在primary节点上面)
#切换到admin库
use admin
#创建系统超级用户myroot,设置密码123456,设置角色root
db.createUser({
user:"root",
pwd:"123456",
roles:[{
role:"root",
db:"admin"
}]
})
或者db.createUser({user:"root",pwd:"123456",roles:[role:"root"]})
# 输出:
Successfully added user: {
"user" : "root",
"roles" : [
{
"role" : "root",
"db" : "admin"
}
]
}
#创建专门管理admin库的账号myadmin,只用来做为用户权限管理
db.createUser({
user:"admin",
pwd:"123456",
roles:[{
role:"userAdminAnyDatabase",
db:"admin"
}]
})
# 输出
Successfully added user: {
"user" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
}
5、创建普通用户
创建普通用户可以在没有开启认证的时候添加,也可以在开启认证之后添加,但是开启认证之后,必须使用有操作admin库的用户登录认证之后才能操作。
#切换到销售数据库db_sales
use db_sales
#创建用户zhangsan,拥有 db_sales 数据库的读写权限readWrite,密码是123456
db.createUser({
user:"zhangsan",
pwd:"123456",
roles:[{
role:"readWrite",
db:"db_sales"
}]
})
# 输出
Successfully added user: {
"user" : "zhangsan",
"roles" : [
{
"role" : "readWrite",
"db" : "db_sales"
}
]
}
#查看已经创建的用户情况
db.system.users.find()
testrs:PRIMARY> use db_sales
testrs:PRIMARY> show users
{
"_id" : "db_sales.zhangsan",
"userId" : UUID("01dbb7f5-0680-4bfd-a01e-bd05bdc517b7"),
"user" : "zhangsan",
"db" : "db_sales",
"roles" : [
{
"role" : "readWrite",
"db" : "db_sales"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
#删除用户
db.dropUser("admin")
#修改密码
db.changeUserPassword("root","123456")
5、认证测试
#切换数据库
use admin
#验证用户名密码
db.auth("root","123456")
6、连接集群
# 如果连接都是其他数据库,可能会失败
mongo mongodb://root:[email protected]:40001,111.111.111.112:40002,111.111.111.113:40003/test?replicaSet=testrs
引用列表: