Mongodb搭建一个环境玩着
想搞个数据库嘛,存一些东西
存一些日志之类的,mongodb貌似挺适合的,做物联网设备上传的数据存储。
以前的是主从,但是主从的话挂了一个主,就没法工作了。
现在的架构,我们可以去看看腾讯云的购买时就可以发现:
副本集群
分片集群
副本集群就是技术主节点挂了,也可以选举出新的主节点来。
而分片集群则是支持无线容量的扩展,把数据分片存储。
docker 搭建Mongodb环境
不管是哪一种架构,我们先用docker来搭建mongodb环境,当然也可以本地安装,这样子你需要多台机器。或者不同的端口号。
这里面我们采用docker来创建,生产环境也一样,只是跑在不同的机器上。
通过docker来创建的话,这里我使用docker-compose比较方便,docker-compose.yaml
脚本如下:
创建一个文件夹:mongodbMaster,里面创建docker-compose.yaml
version: "3"
services:
mongodbMaster:
image: mongo:5 # 镜像和版本
container_name: mongodb-master # 容器名称
restart: always # 挂了会自己重启,开机会自动启动
ports:
- 27027:27017 # master的端口号,外部和内部一样
volumes:
- ./data:/data/db # 把内部的数据存储路径映射到宿主机上的当前目录的data文件夹下
command: --wiredTigerCacheSizeGB 4 --auth # 限制内存大小, 需要认证
environment:
- MONGO_INITDB_ROOT_USERNAME=admin # 管理员账号
- MONGO_INITDB_ROOT_PASSWORD=123456 # 管理员密码
创建一个文件夹:mongodbNode1,里面创建docker-compose.yaml
version: "3"
services:
mongodbNode1:
image: mongo:5 # 镜像和版本
container_name: mongodb-node1 # 容器名称
restart: always # 挂了会自己重启,开机会自动启动
ports:
- 27028:27017 # master的端口号,外部和内部一样
volumes:
- ./data:/data/db # 把内部的数据存储路径映射到宿主机上的当前目录的data文件夹下
command: --wiredTigerCacheSizeGB 4 --auth # 限制内存大小, 需要认证
environment:
- MONGO_INITDB_ROOT_USERNAME=admin # 管理员账号
- MONGO_INITDB_ROOT_PASSWORD=123456 # 管理员密码
创建一个文件夹:mongodbNode2,里面创建docker-compose.yaml
version: "3"
services:
mongodbNode2:
image: mongo:5 # 镜像和版本
container_name: mongodb-node2 # 容器名称
restart: always # 挂了会自己重启,开机会自动启动
ports:
- 27029:27017
volumes:
- ./data:/data/db # 把内部的数据存储路径映射到宿主机上的当前目录的data文件夹下
command: --wiredTigerCacheSizeGB 4 --auth # 限制内存大小, 需要认证
environment:
- MONGO_INITDB_ROOT_USERNAME=admin # 管理员账号
- MONGO_INITDB_ROOT_PASSWORD=123456 # 管理员密码
快速了改了一下,然后就有了3个mongodb了.
启动一下,在对应的docker-compose.yaml
文件目录下:docker-compose up -d
-d是守护式运行,不加-d可以直接看到日志,查看是否有错,如果要看日志可以:docker logs 容器名称
注意端口号,另外就是网络模式,默认是桥接:bridge
副本集群
接下来我们搭建一下副本集群架构
有了前面的通过容器的方式来快速搭建好mongodb数据库,接下来我们配置一下副本集群的方式。
前面只是独立的mongodb,还不能进行副本配置,先生成一个沟通的密码:
openssl rand -base64 10 > ./mongodb.key
10是密码长度,随机的,输出到当前目录下,名字为mongodb.key
我们需要修改docker-compose.yaml
文件如下:
version: "3"
services:
mongodbMaster:
image: mongo:5 # 镜像和版本
container_name: mongodb-master # 容器名称
restart: always # 挂了会自己重启,开机会自动启动
ports:
- 27027:27017 # master的端口号
volumes:
- ./data:/data/db # 把内部的数据存储路径映射到宿主机上的当前目录的data文件夹下
- ./mongodb.key:/data/mongodb.key
command: --wiredTigerCacheSizeGB 4 --auth --replSet iot-mongo-set --keyFile /data/mongodb.key # 限制内存大小, 需要认证
environment:
- MONGO_INITDB_ROOT_USERNAME=admin # 管理员账号
- MONGO_INITDB_ROOT_PASSWORD=123456 # 管理员密码
以上,我们生成了mongodb.key,但是我们不能给太多的权限,否则会报权限太开放的错误。
我们修改一下文件权限为400
chmod 400 mongodb.key
再修改用户组:
chmod 999:999 mongodb.key
修改以后的权限和用户组如下:
再启动,就有了。其他两个节点都这样修改,去掉密码的配置,要同一个Key进行通讯。
version: "3"
services:
mongodbNode1:
image: mongo:5 # 镜像和版本
container_name: mongodb-node1 # 容器名称
restart: always # 挂了会自己重启,开机会自动启动
ports:
- 27028:27017 # node1的端口号
volumes:
- ./data:/data/db # 把内部的数据存储路径映射到宿主机上的当前目录的data文件夹下
- ./mongodb.key:/data/mongodb.key # 把通讯密码映射到容器内部
command: --wiredTigerCacheSizeGB 4 --replSet iot-mongo-set --keyFile /data/mongodb.key # 限制内存大小
version: "3"
services:
mongodbNode2:
image: mongo:5 # 镜像和版本
container_name: mongodb-node2 # 容器名称
restart: always # 挂了会自己重启,开机会自动启动
ports:
- 27029:27017 # node2的端口号
volumes:
- ./data:/data/db # 把内部的数据存储路径映射到宿主机上的当前目录的data文件夹下
- ./mongodb.key:/data/mongodb.key # 把通讯密码映射到容器内部
command: --wiredTigerCacheSizeGB 4 --replSet iot-mongo-set --keyFile /data/mongodb.key # 限制内存大小
配置副本用文字表述就是在master节点上添加其他的副本。就这么简单。
首先我们在master节点上:
rs.initiate()
{ info2: 'no configuration specified. Using a default configuration for the set',
me: 'ea95c5cb4512:27017',
ok: 1
}
目前是初始化,没有副本的。
查看一下状态:
re.status()
{ set: 'iot-mongo-set',
date: 2023-04-07T06:49:47.646Z,
myState: 1,
term: 1,
syncSourceHost: '',
syncSourceId: -1,
heartbeatIntervalMillis: 2000,
majorityVoteCount: 1,
writeMajorityCount: 1,
votingMembersCount: 1,
writableVotingMembersCount: 1,
optimes:
{ lastCommittedOpTime: { ts: Timestamp(1, 1680850179), t: 1 },
lastCommittedWallTime: 2023-04-07T06:49:39.752Z,
readConcernMajorityOpTime: { ts: Timestamp(1, 1680850179), t: 1 },
appliedOpTime: { ts: Timestamp(1, 1680850179), t: 1 },
durableOpTime: { ts: Timestamp(1, 1680850179), t: 1 },
lastAppliedWallTime: 2023-04-07T06:49:39.752Z,
lastDurableWallTime: 2023-04-07T06:49:39.752Z },
lastStableRecoveryTimestamp: Timestamp(1, 1680850129),
electionCandidateMetrics:
{ lastElectionReason: 'electionTimeout',
lastElectionDate: 2023-04-07T06:41:49.578Z,
electionTerm: 1,
lastCommittedOpTimeAtElection: { ts: Timestamp(1, 1680849709), t: -1 },
lastSeenOpTimeAtElection: { ts: Timestamp(1, 1680849709), t: -1 },
numVotesNeeded: 1,
priorityAtElection: 1,
electionTimeoutMillis: 10000,
newTermStartDate: 2023-04-07T06:41:49.673Z,
wMajorityWriteAvailabilityDate: 2023-04-07T06:41:49.730Z },
members:
[ { _id: 0,
name: 'ea95c5cb4512:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 611,
optime: { ts: Timestamp(1, 1680850179), t: 1 },
optimeDate: 2023-04-07T06:49:39.000Z,
lastAppliedWallTime: 2023-04-07T06:49:39.752Z,
lastDurableWallTime: 2023-04-07T06:49:39.752Z,
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp(2, 1680849709),
electionDate: 2023-04-07T06:41:49.000Z,
configVersion: 1,
configTerm: 1,
self: true,
lastHeartbeatMessage: '' } ],
ok: 1,
'$clusterTime':
{ clusterTime: Timestamp(1, 1680850179),
signature:
{ hash: BinData(0, "1cR652DQwAV6mPau1mNAZFy4aeU="),
keyId: NumberLong("7219194529646116869") } },
operationTime: Timestamp(1, 1680850179) }
添加副本:
rs.add("172.17.0.1:27028")
{ ok: 1,
'$clusterTime':
{ clusterTime: Timestamp(1, 1680850999),
signature:
{ hash: BinData(0, "BMvv1dqUXz7EDHQYqUfdYIJotLY="),
keyId: NumberLong("7219194529646116869") } },
operationTime: Timestamp(1, 1680850999) }
再次查看状态:
rs.add("172.17.0.1:27028")
{ ok: 1,
'$clusterTime':
{ clusterTime: Timestamp(1, 1680850999),
signature:
{ hash: BinData(0, "BMvv1dqUXz7EDHQYqUfdYIJotLY="),
keyId: NumberLong("7219194529646116869") } },
operationTime: Timestamp(1, 1680850999) }
rs.status()
{ set: 'iot-mongo-set',
date: 2023-04-07T07:03:36.247Z,
myState: 1,
term: 1,
syncSourceHost: '',
syncSourceId: -1,
heartbeatIntervalMillis: 2000,
majorityVoteCount: 1,
writeMajorityCount: 1,
votingMembersCount: 1,
writableVotingMembersCount: 1,
optimes:
{ lastCommittedOpTime: { ts: Timestamp(1, 1680851009), t: 1 },
lastCommittedWallTime: 2023-04-07T07:03:29.806Z,
readConcernMajorityOpTime: { ts: Timestamp(1, 1680851009), t: 1 },
appliedOpTime: { ts: Timestamp(1, 1680851009), t: 1 },
durableOpTime: { ts: Timestamp(1, 1680851009), t: 1 },
lastAppliedWallTime: 2023-04-07T07:03:29.806Z,
lastDurableWallTime: 2023-04-07T07:03:29.806Z },
lastStableRecoveryTimestamp: Timestamp(1, 1680850969),
electionCandidateMetrics:
{ lastElectionReason: 'electionTimeout',
lastElectionDate: 2023-04-07T06:41:49.578Z,
electionTerm: 1,
lastCommittedOpTimeAtElection: { ts: Timestamp(1, 1680849709), t: -1 },
lastSeenOpTimeAtElection: { ts: Timestamp(1, 1680849709), t: -1 },
numVotesNeeded: 1,
priorityAtElection: 1,
electionTimeoutMillis: 10000,
newTermStartDate: 2023-04-07T06:41:49.673Z,
wMajorityWriteAvailabilityDate: 2023-04-07T06:41:49.730Z },
members:
[ { _id: 0,
name: 'ea95c5cb4512:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 1440,
optime: { ts: Timestamp(1, 1680851009), t: 1 },
optimeDate: 2023-04-07T07:03:29.000Z,
lastAppliedWallTime: 2023-04-07T07:03:29.806Z,
lastDurableWallTime: 2023-04-07T07:03:29.806Z,
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp(2, 1680849709),
electionDate: 2023-04-07T06:41:49.000Z,
configVersion: 2,
configTerm: 1,
self: true,
lastHeartbeatMessage: '' },
{ _id: 1,
name: '172.17.0.1:27028',
health: 1,
state: 0,
stateStr: 'STARTUP',
uptime: 16,
optime: { ts: Timestamp(0, 0), t: -1 },
optimeDurable: { ts: Timestamp(0, 0), t: -1 },
optimeDate: 1970-01-01T00:00:00.000Z,
optimeDurableDate: 1970-01-01T00:00:00.000Z,
lastAppliedWallTime: 1970-01-01T00:00:00.000Z,
lastDurableWallTime: 1970-01-01T00:00:00.000Z,
lastHeartbeat: 2023-04-07T07:03:35.580Z,
lastHeartbeatRecv: 1970-01-01T00:00:00.000Z,
pingMs: 0,
lastHeartbeatMessage: '',
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
configVersion: -2,
configTerm: -1 } ],
ok: 1,
'$clusterTime':
{ clusterTime: Timestamp(1, 1680851009),
signature:
{ hash: BinData(0, "J1TFrFf+ErD/LVhICCTXagfdUfI="),
keyId: NumberLong("7219194529646116869") } },
operationTime: Timestamp(1, 1680851009) }
就会发现多了一个成员了。
但是这里会有个问题:
主设备的name是name: ea95c5cb4512:27017
,副本会通过这个地址来同步主本的数据,访问的时候会报错
得需要修改此
cfg = rs.conf()
{ _id: 'iot-mongo-set',
version: 4,
term: 1,
members:
[ { _id: 0,
host: 'ea95c5cb4512:27027',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: 0,
votes: 1 },
{ _id: 1,
host: '192.168.220.128:27028',
arbiterOnly: false,
buildIndexes: true,
hidden: false,
priority: 1,
tags: {},
secondaryDelaySecs: 0,
votes: 1 } ],
protocolVersion: 1,
writeConcernMajorityJournalDefault: true,
settings:
{ chainingAllowed: true,
heartbeatIntervalMillis: 2000,
heartbeatTimeoutSecs: 10,
electionTimeoutMillis: 10000,
catchUpTimeoutMillis: -1,
catchUpTakeoverDelayMillis: 30000,
getLastErrorModes: {},
getLastErrorDefaults: { w: 1, wtimeout: 0 },
replicaSetId: ObjectId("642fcba05e17e46d5feeac74") } }
修改一下host
cfg.members[0].host="192.168.220.128:27027"
重置一下配置
rs.reconfig(cfg)
这样子就可以相互链接上了。
接着用mongodb compass连接上,创建一些内容:
另外,登录一下27028的mongodb
原因:not master and slaveOk=false
我的是5.0的版本:
rs.secondaryOk()
如果是低版本的
rs.slaveOk()
这样子就可以了,分片集群的下次再写吧,先到这里。
项目连接的就不说了,很简单的。
相关问题
- 权限太大的问题
permissions on /data/mongodb.key are too open"
修改一下权限为600
chmod 600 mongodb.key
- 文件坏的
error opening file: /data/mongodb.key: bad file"
修改一下用户组
chown 999:999 mongodb.key