# 部署
MongoDB 常见的部署架构:
- 单实例
- 主从集群
- 与 MySQL 的主从集群类似。
- MongoDB 4.0 版本开始不支持部署主从集群,需要换成副本集群。
- 副本集群
- 分片集群
# 单实例
# 部署
用 yum 安装:
wget https://repo.mongodb.org/yum/redhat/7/mongodb-org/4.0/x86_64/RPMS/mongodb-org-server-4.0.5-1.el7.x86_64.rpm wget https://repo.mongodb.org/yum/redhat/7/mongodb-org/4.0/x86_64/RPMS/mongodb-org-shell-4.0.5-1.el7.x86_64.rpm wget https://repo.mongodb.org/yum/redhat/7/mongodb-org/4.0/x86_64/RPMS/mongodb-org-tools-4.0.5-1.el7.x86_64.rpm wget https://repo.mongodb.org/yum/redhat/7/mongodb-org/4.0/x86_64/RPMS/mongodb-org-mongos-4.0.5-1.el7.x86_64.rpm yum install -y mongodb-org-*.rpm rm -f mongodb-org-*.rpm
然后启动:
mongod # 启动 mongo 服务器 -f /etc/mongod.conf # 使用指定的配置文件
- 服务器启动时,默认不会读取配置文件,在前台运行,监听端口 27017 ,
或者用 docker-compose 部署:
version: "3" services: mongo: container_name: mongo image: mongo:5.0.5 command: [mongod, -f, /etc/mongod.conf] restart: unless-stopped environment: MONGO_INITDB_ROOT_USERNAME: root # 创建管理员用户 MONGO_INITDB_ROOT_PASSWORD: ****** ports: - 27017:27017 volumes: - /etc/localtime:/etc/localtime:ro - ./mongod.conf:/etc/mongod.conf - ./data:/data/db # 官方镜像将 /data/db 目录声明为了 volume ,不挂载到该目录则会自动挂载一个匿名 volume
- 需要调整挂载目录的权限:
chown -R 999 data
- 需要调整挂载目录的权限:
# 管理
- 停止服务器时,使用 kill 命令可能导致服务器异常终止。
- 建议使用
mongod -f /etc/mongod.conf --shutdown
- 或者在客户端执行:
use admin db.shutdownServer()
- 建议使用
# 客户端
命令:
mongo [options] [server_uri] [script.js] # 启动客户端
-u <username>
-p <password>
- Mongo 服务器的 URI 采用以下格式:
mongodb://[username:password@]host1[:port1][,hostN[:portN]]...[/db][?options]]
- 例:
mongodb://127.0.0.1:27017/test # mongodb 客户端默认连接到 localhost:6379 服务器的 test 数据库 mongodb://root:******@127.0.0.1:27017/test?authSource=admin # 传入用户名、密码,并通过 URI 参数指定验证数据库 mongodb://localhost,localhost:27018,localhost:27019/admin # 可以同时连接多个服务器
- 例:
- 启动客户端时,默认是打开一个 JavaScript 终端,因此可以执行 js 命令、定义变量、定义函数。
- 也可以指定一个要执行的 js 脚本,或者从 stdin 传入要执行的 js 命令。
# 备份数据
# 导出
mongodump
-h <host>[:port]
--authenticationDatabase=admin
-u <username>
-p <password>
-d <db> # 只处理指定的数据库(默认会导出所有数据库)
-c <collection> # 只处理指定的集合。只能指定一个集合,如果不指定则处理所有集合
-j 4 # 同时最多处理几个集合
-q <expression> # --query ,用一个 JSON 格式的表达式筛选文档,比如 '{year: "2021"}'
-o <path> # 导出之后保存到指定目录,默认为 ./dump
--gzip # 导出时进行 gzip 压缩
- 默认会导出所有数据库,在目标目录下按数据库名分别创建子目录,为每个集合保存
<collection>.bson
和<collection>.metadata.json
两个数据文件。 - 导出时,如果不进行 gzip 压缩,大概占用的磁盘空间为原数据的 200% 。如果进行压缩,大概占用 50% 。
- 该压缩文件不支持用 tar 命令解压。
mongoexport # 导出为 JSON 或 CSV 格式,兼容 mongodump 的大部分参数
--out out.json # 导出之后保存到指定文件,默认输出到 stdout
--type json # 导出格式,默认为 json
--pretty # 导出格式为 JSON 时,进行缩进排版。默认是每个文档占一行
--limit <int> # 限制导出的文档数
# 导入
- mongodump 导出的数据要用 mongorestore 命令导入。而 mongoexport 导出的数据,以及其它来源的 JSON、CSV 数据,要用 mongoimport 命令导入。
mongorestore <path> # 指定要导入的 BSON 文件。也可以指定目录,这会自动发现该目录下的 bson 文件,但不会发现子目录的
-h <host>[:port]
--authenticationDatabase=admin
-u <username>
-p <password>
-d <db>
-c <collection>
-j 4
--gzip # 导入时进行 gzip 解压
--drop # 在导入每个集合之前先删除同名的
--stopOnError # 遇到报错时立即停止(默认不会立即停止,且命令的返回码依然为 0 )
mongoimport <file> # 指定文件,导入 JSON 或 CSV 格式的数据,兼容 mongorestore 的大部分参数
# 副本集群
MongoDB v4.0 开始弃用主从集群,只支持副本集群(Replication)。
副本集群由多个 MongoDB server 组成,server 的角色分为三种:
- Primary
- :主节点,负责处理客户端的读、写请求。
- 同时只能存在一个。
- Secondary
- :从节点,负责复制主节点的数据。
- 可以部署一个或多个。
- 主节点会将所有数据库操作记录在 oplog 中,而从节点会定期从主节点复制 oplog ,异步应用其中的操作。
- 从节点不能处理客户端的写请求,但能处理读请求。
- 不过从节点采用异步复制,可能没有最新的数据,因此客户端一般默认将读、写请求都发给主节点。
- Arbiter
- :仲裁节点。不同步数据(因此不容易出故障),仅参与投票,不能被选举。
- 可以部署任意个(包括零个)。
- Primary
当主节点不可用时,其它节点会自动选出一个新的主节点。
- 副本集中要有超过半数的节点在线,才能开始选举。
- 选举过程有几秒长。
MongoDB 限制了一个副本集最多包含 50 个成员,其中最多 7 个投票成员。
- 建议给副本集部署 1 个主节点 + 至少 2 个从节点。此时即使一个节点发生故障,副本集依然可以工作。
- 与 zk 集群类似,副本集包含的投票节点的数量建议为奇数,为偶数时并不会提高可靠性。
oplog :操作日志(operation log),存储在 local 数据库的一个集合中。
- oplog 记录的操作具有幂等性,可能将多个写操作合并为一个写操作。
- oplog 的默认大小为磁盘空间的 5% 。
# 部署
集群节点之间默认采用密钥文件进行认证。先生成密钥文件:
openssl rand -base64 512 > mongo.key chown mongod mongo.key chmod 400 mongo.key
然后将密钥文件拷贝到各个节点。
在各个节点的配置文件中加入:
replication: # 让 mongod 工作在副本集模式。默认为 Standalone 模式 replSetName: rs0 # 副本集名称。同一副本集中的所有节点必须采用相同的 replSetName security: authorization: enabled keyFile: /etc/mongo/mongo.key # 密钥文件的路径
登录一个节点,启动副本集:
rs.initiate({ _id: "rs0", // 副本集的名称 members: [ // 副本集的成员列表 { _id: 0, host: "mongo-1:27017" }, { _id: 1, host: "mongo-2:27017" }, { _id: 2, host: "mongo-3:27017", priority: 0} ] })
- 副本集必须初始化一次之后才能启动,也只需要初始化一次。
- 不允许在 priority 为 0 的节点或仲裁节点上进行初始化。
# 管理
相关命令:
rs.initiate(cfg) // 启动副本集,可传入一些配置参数进行初始化,其余的配置参数则采用默认值
rs.reconfig(cfg) // 重新配置副本集,可覆盖已有的配置参数
rs.conf() // 显示副本集的配置
rs.status() // 显示副本集的状态
rs.add("mongo-1:27017") // 添加从节点
rs.remove("mongo-1:27017") // 删除从节点
rs.addArb("mongo-4:27017") // 添加仲裁节点
db.printReplicationInfo() // 查看 oplog 的状态
db.printSlaveReplicationInfo() // 查看从节点的同步状态
例:查看副本集的状态
rs0:SECONDARY> rs.status() { "set" : "rs0", "date" : ISODate("2019-12-19T09:22:27.736Z"), "myState" : 1, "term" : NumberLong(1), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 2, "writeMajorityCount" : 2, ... "members" : [ // 所有节点的信息 { "_id" : 0, "name" : "mongo-1:27017", "ip" : "10.244.25.178", "health" : 1, // 0 代表下线,1 代表在线 "state" : 1, // 该节点的状态 "stateStr" : "PRIMARY", // 该节点的状态描述 "uptime" : 1798, // 该节点的在线时长 "optime" : { "ts" : Timestamp(1576746303, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2019-12-19T09:05:03Z"), // 该节点最后一次同步 oplog 的时间 "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "could not find member to sync from", "configVersion" : 1, "self" : true, // 该节点是否为当前登录的节点 "lastHeartbeatMessage" : "" }, ...
- 节点的状态分为以下几种,分别对应一个数字编号:
0 STARTUP # 已启动,没有加入副本集 1 PRIMARY 2 SECONDARY 3 RECOVERING # 恢复中,可能是正在启动或回滚 5 STARTUP2 # 已启动,而且加入了某个副本集,正在进行初始同步。随后会变成 PRIMARY、SECONDARY 等状态 6 UNKNOWN # 其它节点不能判断该节点的状态 7 ARBITER # 仲裁者 8 DOWN # 其它节点不能访问该节点 9 ROLLBACK # 回滚中 10 REMOVED # 该节点从副本集中移除了
- 节点的状态分为以下几种,分别对应一个数字编号:
例:修改副本集的配置
rs0:PRIMARY> rs.conf() { "_id" : "rs0", "version" : 1, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "mongo-2:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, // 该节点是否隐藏。隐藏节点的 priority 为 0 ,不能被选举,但是可以投票 "priority" : 1, // 该节点在竞选主节点时的优先级,取值范围为 0.0~1000.0 。取值越大则越容易当选,取值为 0 则不会当选 "tags" : {}, "slaveDelay" : NumberLong(0), "votes" : 1 // 该节点是否有投票权 }, ...
cfg = rs.conf() cfg.members[2].priority = 0 rs.reconfig(cfg)
# 分片集群
:Shard Cluster 。将数据分散存储到多个 MongoDB ,从而横向扩容。