一、MongoDB 核心概念与架构解析
1.1 MongoDB 本质特征
MongoDB 作为开源文档型 NoSQL 数据库,其设计哲学围绕灵活数据模型与水平扩展能力展开。区别于关系型数据库的表结构,MongoDB 采用类似 JSON 的 BSON 格式存储文档,允许同一集合内文档具有不同字段结构,实现真正的无模式(Schema-less)设计。例如:
{"_id": ObjectId("5146bb52d85242700600013"),"name": "Mark Hanks","email": "mark@abc.com","age": 25,"address": {"city": "Los Angeles","zip": "90001"}
}
{"_id": ObjectId("5146bb52d85242700600014"),"name": "Richard Peter","email": "richard@abc.com","age": 31,"hobbies": ["reading", "hiking"]
}
上述两个文档同属一个集合,但字段类型与结构差异显著,体现了 MongoDB 的数据灵活性。
1.2 核心概念映射
SQL 概念 | MongoDB 概念 | 说明 |
---|---|---|
数据库 (Database) | 数据库 (Database) | 数据存储容器,默认包含 admin、config、local 等系统数据库 |
表 (Table) | 集合 (Collection) | 无模式文档容器,集合内文档可动态定义字段 |
行 (Row) | 文档 (Document) | BSON 格式数据单元,支持嵌套文档、数组等复杂结构 |
列 (Column) | 字段 (Field) | 文档中的键值对,字段值可包含多种数据类型 |
索引 (Index) | 索引 (Index) | 支持单字段、多字段、文本等索引类型,默认创建_id 主键索引 |
事务 (Transaction) | 事务 (Transaction) | 从 4.0 版本开始支持多文档事务,确保原子性操作 |
1.3 关键特性解析
- 索引优化查询:通过
db.collection.createIndex({field: 1})
创建索引,支持对嵌套字段(如address.city
)建立索引,提升查询性能。 - 水平扩展与分片:通过 Sharding 技术将数据分布到多个分片(Shard),每个分片可独立处理读写请求,解决大数据量存储与高并发问题。
- MapReduce 批量处理:使用 JavaScript 编写 Map 和 Reduce 函数,实现数据聚合与分析,例如统计用户地域分布:
db.users.mapReduce(function() { emit(this.address.city, 1); },function(key, values) { return Array.sum(values); },{ out: "city_counts" } );
- GridFS 大文件存储:自动将大文件分割为≤16MB 的块存储,支持图片、视频等二进制数据存储,通过
fs.files
和fs.chunks
集合管理。
二、Linux 环境下 MongoDB 安装与配置
2.1 系统依赖准备
在 RHEL/CentOS 系统中,安装必要依赖包:
sudo dnf install -y libcurl openssl gcc make perl
若需编译安装 OpenSSL 1.1(MongoDB 6.0 + 依赖),执行:
wget https://www.openssl.org/source/openssl-1.1.1w.tar.gz
tar xzf openssl-1.1.1w.tar.gz
cd openssl-1.1.1w
./config --prefix=/opt/openssl11 --openssldir=/opt/openssl/ssl
make -j$(nproc)
make install
echo 'export LD_LIBRARY_PATH=/opt/openssl11/lib:$LD_LIBRARY_PATH' | sudo tee /etc/profile.d/openssl11.sh
source /etc/profile.d/openssl11.sh
2.2 安装包部署
下载 MongoDB 社区版安装包(以 8.0.8 版本为例):
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel8-8.0.8.tgz
tar -zxvf mongodb-linux-x86_64-rhel8-8.0.8.tgz
sudo mv mongodb-linux-x86_64-rhel8-8.0.8 /usr/local/mongodb
配置环境变量,编辑/etc/profile
:
echo 'export PATH=/usr/local/mongodb/bin:$PATH' >> /etc/profile
source /etc/profile
2.3 初始化数据目录
创建默认数据存储目录与日志目录:
sudo mkdir -p /var/lib/mongo /var/log/mongodb
sudo chown -R $(whoami) /var/lib/mongo /var/log/mongodb
2.4 启动服务
带参数启动(适用于临时测试):
mongod --dbpath /var/lib/mongo --logpath /var/log/mongodb/mongod.log --fork
输出child process started successfully
表示启动成功。若需配置文件启动,创建/etc/mongod.conf
:
systemLog:destination: filepath: /var/log/mongodb/mongod.loglogAppend: true
storage:dbPath: /var/lib/mongojournal:enabled: true
processManagement:fork: true
net:port: 27017bindIp: 127.0.0.1
启动服务:
sudo systemctl start mongod
sudo systemctl enable mongod # 设置开机自启
三、MongoDB Shell 深度使用
3.1 Shell 安装与配置
下载 MongoDB Shell 工具(mongosh):
wget https://downloads.mongodb.com/compass/mongosh-2.5.0-linux-x64-openssl3.tgz
tar xzf mongosh-2.5.0-linux-x64-openssl3.tgz
cd mongosh-2.5.0-linux-x64-openssl3/bin
sudo cp mongosh /usr/local/bin/
sudo cp mongosh_crypt_v1.so /usr/local/lib/
3.2 连接与认证
- 连接本地数据库(默认端口 27017):
mongosh
- 连接远程服务器:
mongosh "mongodb://user:password@remote-host:27017/dbname"
- 认证示例(切换到 admin 数据库):
use admin db.auth("root", "secure-password")
3.3 常用操作命令
- 查看服务器信息:
db.serverStatus()
- 显示所有数据库:
show dbs
- 显示当前数据库:
db
- 显示当前集合:
show collections
四、数据库管理实战
4.1 创建与删除数据库
- 创建数据库(显式切换,插入数据后生效):
use mydatabase db.mycollection.insertOne({name: "init-doc"}) // 触发数据库创建
- 删除数据库:
use mydatabase db.dropDatabase()
4.2 系统数据库解析
- admin:存储用户认证信息,拥有 root 角色的用户可在此数据库执行全局管理操作。
- config:分片集群元数据存储库,记录分片节点、数据块分布等信息。
- local:存储本地节点数据,如副本集 oplog 日志,数据不会同步到其他节点。
4.3 权限控制基础
MongoDB 权限系统基于角色(Role)和数据库(Database)实现细粒度控制,内置角色包括:
- 数据库角色:read、readWrite、dbAdmin(管理数据库)等。
- 集群角色:clusterAdmin(管理集群)、clusterMonitor(监控集群)等。
- 超级用户角色:root(拥有所有权限)、userAdmin(管理用户)等。
五、集合管理高级操作
5.1 创建集合与模式验证
- 常规创建:
db.createCollection("users")
- 创建固定大小集合(Capped Collection),用于日志类场景:
db.createCollection("logs", {capped: true,size: 10485760, // 10MBmax: 5000 // 最大文档数 })
- 文档验证(JSON Schema 验证):
db.createCollection("users", {validator: {$jsonSchema: {bsonType: "object",required: ["name", "email"],properties: {name: { bsonType: "string", minLength: 2 },email: { bsonType: "string", pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$" }}}},validationLevel: "strict" })
5.2 重命名与删除集合
- 重命名集合(需在 admin 数据库执行):
use admin db.adminCommand({renameCollection: "mydatabase.old_users",to: "mydatabase.new_users",dropTarget: true // 若目标存在则删除 })
- 删除集合:
db.users.drop()
六、文档操作核心命令
6.1 插入操作
- 单文档插入:
db.users.insertOne({name: "Alice",age: 25,tags: ["engineer", "hiker"] })
- 多文档插入(有序插入,默认
ordered: true
):db.users.insertMany([{ name: "Bob", age: 30, city: "New York" },{ name: "Charlie", age: 35, city: "London" } ])
6.2 查询操作
- 基础查询(查询 age>25 的文档,返回 name 和 age 字段):
db.users.find({ age: { $gt: 25 } },{ name: 1, age: 1, _id: 0 } ).pretty() // 格式化输出
- 复杂查询(查询包含 "engineer" 标签且年龄在 25-35 之间的文档):
db.users.find({tags: { $in: ["engineer"] },age: { $gte: 25, $lte: 35 } })
- 聚合查询(统计各城市用户数量):
db.users.aggregate([{ $group: { _id: "$city", count: { $sum: 1 } } } ])
6.3 更新操作
- 单文档更新(设置 age 为 26):
db.users.updateOne({ name: "Alice" },{ $set: { age: 26 } } )
- 多文档更新(将所有年龄 < 30 的用户状态设为 "junior"):
db.users.updateMany({ age: { $lt: 30 } },{ $set: { status: "junior" } } )
- 替换文档(完全覆盖旧文档):
db.users.replaceOne({ name: "Bob" },{ name: "Bob", age: 31, city: "Los Angeles", status: "senior" } )
6.4 删除操作
- 单文档删除:
db.users.deleteOne({ name: "Charlie" })
- 多文档删除(删除所有状态为 "inactive" 的文档):
db.users.deleteMany({ status: "inactive" })
七、数据备份与恢复策略
7.1 备份工具安装
sudo rpm -ivh mongodb-database-tools-rhel70-x86_64-100.12.0.rpm
7.2 全量备份
- 备份所有数据库到
/data/backup
目录:mongodump --out /data/backup
- 备份指定数据库(如
mydatabase
):mongodump -d mydatabase -o /data/backup/mydb
- 备份指定集合(如
users
集合):mongodump -d mydatabase -c users -o /data/backup/users
7.3 增量备份(基于 Oplog)
通过复制local.oplog.rs
集合实现增量备份,适用于灾难恢复场景:
use local
db.oplog.rs.find().sort({ $natural: -1 }).limit(1) // 获取最新 oplog 时间戳
7.4 数据恢复
- 从备份目录恢复所有数据库:
mongorestore --dir /data/backup
- 恢复指定数据库到新名称(如将备份的
mydatabase
恢复为newdb
):mongorestore -d newdb /data/backup/mydatabase
- 恢复时先删除现有数据:
mongorestore --drop --dir /data/backup/mydatabase
八、用户管理与安全配置
8.1 创建用户与分配角色
- 在
mydatabase
数据库创建读写用户:use mydatabase db.createUser({user: "app_user",pwd: "secure_password",roles: [{ role: "readWrite", db: "mydatabase" }] })
- 创建具有集群管理权限的用户(在 admin 数据库):
use admin db.createUser({user: "cluster_admin",pwd: "admin_password",roles: [{ role: "clusterAdmin", db: "admin" }] })
8.2 启用身份验证
编辑配置文件/etc/mongod.conf
,添加:
security:authorization: "enabled"
重启服务使配置生效:
sudo systemctl restart mongod
8.3 连接时指定认证数据库
mongosh --host localhost --port 27017 -u "app_user" -p "secure_password" --authenticationDatabase "mydatabase"
8.4 权限验证与角色管理
- 验证用户权限:
db.auth("app_user", "secure_password") // 返回1表示认证成功
- 修改用户角色:
use mydatabase db.updateUser("app_user", {addToRoles: [{ role: "dbAdmin", db: "mydatabase" }] })
- 删除用户:
db.dropUser("app_user")
九、性能优化与最佳实践
9.1 索引优化
- 为高频查询字段创建索引:
db.users.createIndex({ email: 1 }, { unique: true }) // 唯一索引 db.users.createIndex({ age: 1, city: 1 }) // 复合索引
- 查看查询执行计划:
db.users.find({ age: 25 }).explain("executionStats")
9.2 连接池管理
在应用层配置连接池参数(以 Node.js 为例):
const MongoClient = require('mongodb').MongoClient;
const client = new MongoClient('mongodb://localhost:27017', {poolSize: 10, // 最大连接数maxIdleTimeMS: 30000 // 空闲连接超时时间
});
9.3 存储引擎选择
MongoDB 默认使用 WiredTiger 存储引擎,支持文档级锁和压缩(如 ZSTD 压缩),配置示例:
storage:engine: wiredTigerwiredTiger:engineConfig:cacheSizeGB: 2 // 缓存大小collectionConfig:blockCompressor: zstd
十、常见问题与解决方案
10.1 无法连接服务器
- 检查端口是否开放:
sudo firewall-cmd --add-port=27017/tcp --permanent
- 确认 MongoDB 服务运行状态:
sudo systemctl status mongod
10.2 数据文件过大
- 启用 WiredTiger 压缩减少存储占用
- 删除无用集合或文档:
db.large_collection.drop()
10.3 慢查询优化
- 通过慢查询日志定位问题:
十一、副本集(Replica Set)架构与配置
11.1 副本集核心概念
- 主节点(Primary):唯一负责处理写入操作的节点,维护 oplog(操作日志)。
- 从节点(Secondary):复制主节点数据,可用于读操作或在主节点故障时自动切换为主节点。
- 仲裁节点(Arbiter):不存储数据,仅参与选举投票,用于奇数节点部署以避免脑裂。
11.2 部署三节点副本集
11.2.1 配置文件准备
创建三个节点的数据目录与日志目录(以节点 1 为例):
sudo mkdir -p /data/rs1/{data,log}
sudo chown -R $(whoami) /data/rs1
编辑mongod.conf
配置文件:
systemLog:path: /data/rs1/log/mongod.log
storage:dbPath: /data/rs1/data
net:port: 27018bindIp: 0.0.0.0
replication:replSetName: "my_repl_set" # 副本集名称
11.2.2 启动节点并初始化
启动三个节点(端口分别为 27018、27019、27020):
mongod -f /etc/mongod1.conf
mongod -f /etc/mongod2.conf
mongod -f /etc/mongod3.conf
连接任一节点初始化副本集:
mongosh --port 27018
use admin
rs.initiate({_id: "my_repl_set",members: [{ _id: 0, host: "server1:27018" },{ _id: 1, host: "server2:27019" },{ _id: 2, host: "server3:27020", arbiterOnly: true } // 仲裁节点]
})
11.2.3 验证副本集状态
rs.status() // 查看副本集成员状态
rs.isMaster() // 确认主节点
十二、分片集群(Sharding)部署与管理
12.1 分片集群组件
- 分片节点(Shard):存储实际数据,可由副本集构成以提高可用性。
- 配置服务器(Config Server):存储分片元数据(如数据块分布、路由信息),建议部署为三节点副本集。
- 路由节点(mongos):客户端连接入口,负责解析查询并路由到对应分片。
12.2 部署三分片集群
12.2.1 启动配置服务器副本集
创建配置服务器数据目录:
sudo mkdir -p /data/config{1,2,3}/data
配置文件config.conf
:
storage:dbPath: /data/config1/data
replication:replSetName: "config_rs"
net:port: 27019
初始化配置服务器副本集:
mongosh --port 27019
rs.initiate({ _id: "config_rs", members: [{ _id: 0, host: "server1:27019" }] })
12.2.2 启动分片节点(副本集形式)
每个分片节点配置文件shard.conf
:
storage:dbPath: /data/shard1/data
replication:replSetName: "shard_rs1"
sharding:clusterRole: shardsvr // 标识为分片节点
net:port: 27020
初始化分片副本集:
mongosh --port 27020
rs.initiate({ _id: "shard_rs1", members: [{ _id: 0, host: "server1:27020" }] })
12.2.3 启动路由节点
mongos --configdb config_rs/server1:27019,server2:27019,server3:27019 --port 27017
12.2.4 添加分片到集群
mongosh --port 27017
sh.addShard("shard_rs1/server1:27020")
sh.addShard("shard_rs2/server2:27021")
sh.addShard("shard_rs3/server3:27022")
12.2.5 启用分片并设置分片键
use mydatabase
sh.enableSharding("mydatabase")
sh.shardCollection("mydatabase.users", { user_id: 1 }) // 按user_id哈希分片
十三、GridFS 文件存储实战
13.1 存储大文件
使用 MongoDB Shell 存储图片文件:
const fs = require('fs');
const Grid = require('gridfs-stream');
const mongoose = require('mongoose');mongoose.connect('mongodb://localhost:27017/mydb');
const gfs = Grid(mongoose.connection.db, mongoose.mongo);const writableStream = gfs.createWriteStream({filename: 'example.jpg',mode: 'w',contentType: 'image/jpeg'
});const readStream = fs.createReadStream('/path/to/example.jpg');
readStream.pipe(writableStream);writableStream.on('close', (file) => {console.log('File stored with _id:', file._id);
});
13.2 检索与下载文件
gfs.createReadStream({ filename: 'example.jpg' }).pipe(fs.createWriteStream('/path/to/downloaded.jpg')).on('close', () => console.log('File downloaded successfully'));
13.3 删除文件
gfs.remove({ _id: ObjectId("60c72b2f9b1d8b5a5f8e2b2d") }, (err) => {if (!err) console.log('File deleted');
});
十四、事务操作(MongoDB 4.0+)
14.1 多文档事务示例
在电商场景中,同时更新订单状态与库存:
const session = db.startSession();
try {session.withTransaction(() => {// 更新订单状态为"已付款"db.orders.updateOne({ _id: orderId },{ $set: { status: "paid" } },{ session });// 扣减库存db.stocks.updateOne({ productId: productId },{ $inc: { quantity: -1 } },{ session });});session.commitTransaction();console.log("Transaction committed");
} catch (err) {session.abortTransaction();console.error("Transaction aborted:", err);
} finally {session.endSession();
}
14.2 事务注意事项
- 事务仅支持写操作(插入、更新、删除)。
- 跨分片事务需确保分片键在事务涉及的文档中一致。
- 建议事务操作时间控制在秒级以内,避免锁竞争。
十五、监控与性能调优工具
15.1 内置监控命令
- 服务器状态:
db.serverStatus()
返回内存、CPU、磁盘等关键指标。 - 当前操作:
db.currentOp()
查看正在执行的操作,用于诊断阻塞问题。 - 慢查询日志:配置
slowOpThresholdMs
后,慢查询会被记录到日志。
15.2 可视化工具
- MongoDB Compass:官方图形化工具,支持查询构建、索引分析、性能监控。
- MongoDB Atlas:云托管服务,提供实时监控仪表盘、自动扩缩容等功能。
- Prometheus + Grafana:通过
mongodb-exporter
采集指标,配置可视化面板:# prometheus.yml scrape_configs:- job_name: 'mongodb'static_configs:- targets: ['localhost:27017']
十六、故障排查与恢复流程
16.1 主节点故障处理
- 副本集自动选举新主节点(需仲裁节点或多数从节点存活)。
- 若自动选举失败,手动提升从节点为主节点:
rs.slaveOk() // 允许从节点读操作 rs.promote("server2:27019") // 提升为新主节点
16.2 数据文件损坏恢复
- 使用
mongod --repair
命令修复数据文件:mongod --dbpath /var/lib/mongo --repair
- 从最近的全量备份恢复,并应用增量 oplog 日志。
16.3 误删除数据恢复
- 通过
mongorestore
从备份恢复指定集合或文档。 - 若启用了 WiredTiger 存储引擎的时间点恢复(PITR),可恢复到任意时间点:
mongorestore --dir /backup --timestamp 2025-06-01T12:00:00
十七、与其他系统集成
17.1 与 ETL 工具集成
- Apache Spark:通过 MongoDB Spark Connector 读取数据:
val df = spark.read.format("mongodb").option("uri", "mongodb://localhost:27017/mydb.users").load()
- Apache Flink:使用 MongoDB sink 将实时数据写入数据库:
MongoSink<String> sink = MongoSink.builder().withUri("mongodb://localhost:27017/mydb.logs").withDocumentMapper(new JsonDocumentMapper()).build();
17.2 与 BI 工具集成
- Tableau:通过 ODBC 驱动连接 MongoDB,构建数据可视化报表。
- Power BI:使用 MongoDB 插件直接导入文档数据,支持聚合与过滤操作。
十八、最佳实践总结
18.1 数据模型设计原则
- 嵌入优先:将关联数据(如用户地址、订单详情)嵌入主文档,减少查询次数。
- 避免过度嵌套:若嵌套文档过大(如超过 16MB),改用引用(Reference)模式。
- 预聚合数据:对高频统计字段(如点赞数、评论数)进行预计算,存储在文档中。
18.2 生产环境配置建议
- 存储引擎:使用 WiredTiger,启用 ZSTD 压缩(
blockCompressor: zstd
)。 - 索引策略:仅对高频查询字段创建索引,避免索引膨胀。
- 连接安全:启用 TLS/SSL 加密(
net.ssl.mode: requireSSL
),禁止公网直接访问。
18.3 运维流程规范
- 定期备份:每日全量备份 + 每小时增量备份,备份数据异地存储。
- 监控告警:设置 CPU 利用率 > 80%、内存利用率 > 90%、慢查询数 > 10 条 / 分钟等告警规则。
- 版本管理:生产环境使用 LTS 版本(如 6.0.x),避免使用开发版或边缘版本。