Mongodb课程

发布时间:2026/7/26 23:17:45

Mongodb课程 第一阶段MongoDB 基础入门1.什么是mongodbMongoDB 是一款开源、跨平台的分布式文档型 NoSQL 数据库由 MongoDB Inc. 公司开发2007 年首次发布。文档型非关系数据库用类似 JSON 的结构存储数据分类NoSQL非关系型数据库区别于 MySQL、Oracle 这类传统关系型数据库RDBMS适合互联网业务用户信息、博客、评论、商品详情核心存储单元文档Document而非关系库的 “行”数据格式基于BSON二进制 JSON兼容 JSON支持数字、字符串、数组、嵌套对象、日期、二进制等复杂类型2.对比mysqlMongoDB 概念MySQL 对应概念说明数据库 (Database)数据库独立数据仓库集合 (Collection)数据表 (table)存放一批同类文档无需提前定义表结构文档 (Document)行 (row)一条完整数据键值对结构字段 (Field)列 (column)文档里的 key_id主键 (primary key)文档唯一标识自动生成示例一条文档{ _id: ObjectId(60xxxxx), name: 张三, age: 22, hobby: [篮球,编程], address: {city:长沙,district:雨花区} }3.数据格式bson与ObjectId原理1、BSON二进制JSON是MongoDB数据存储格式支持更多数据类型日期、二进制、浮点、ObjectId等。2、_id 主键字段唯一标识文档默认自动生成不可重复ObjectId结构4字节时间戳3字节机器ID2字节进程ID3字节自增计数器自带时间属性可通过_id快速提取文档创建时间4.客户端工具# 带账号密码 mongosh -u admin -p 123456 --authenticationDatabase admin 127.0.0.1:27017 # 直接指定数据库 mongosh 127.0.0.1:27017/testdb // 查看所有数据库 show dbs show databases // 切换/创建数据库不存在则自动创建插入数据后才持久化,隐式创建 use testdb // 查看当前所在库 db // 查看当前库所有集合 show collections show tables // 手动创建集合一般无需手动插入数据自动生成 db.createCollection(user) // 删除集合 db.user.drop()5.CURD语法1. 插入文档 insertOne/insertManyinsertOne 插入单条db.user.insertOne({ name: 张三, age: 20, hobby: [篮球, 游戏], addr: { city: 长沙 } })insertMany 批量插入多条db.user.insertMany([ {name:李四,age:22}, {name:王五,age:25} ])2. 查询 find () /findOne ()// 所有数据 db.user.find() // 格式化输出美观 db.user.find().pretty() // 查询第一条匹配数据 db.user.findOne({name:张三}) // 查询所有匹配的数据 db.user.find({name:张三})条件查询// 等于匹配 db.user.find({name:张三}) // 比较运算符 // $gt 大于、$gte大于等于、$lt小于、$lte小于等于、$ne不等于 db.user.find({age: {$gt: 20}}) // 多条件同时满足 and db.user.find({age:{$gt:18}, name:李四}) // $or 或条件 db.user.find({ $or: [ {age: {$lt:20}}, {name:王五} ] }) // in 匹配多个值 db.user.find({age: {$in: [20,22,25]}})投影只返回指定字段1 显示0 隐藏// 只显示 name、age隐藏 _id db.user.find({age:{$gt:18}}, {name:1, age:1, _id:0})分页、排序、数量// sort 排序1升序 -1降序 db.user.find().sort({age: -1}) // limit 取前N条 db.user.find().limit(2) // skip 跳过N条分页 db.user.find().skip(1).limit(2) // 统计总条数 db.user.countDocuments({age: {$gt:18}})3. 更新 updateOne /updateMany更新操作必须搭配$set否则会覆盖整条文档// updateOne只更新第一条匹配数据 db.user.updateOne( {name:张三}, {$set: {age: 21, sex: 男}} // 新增/修改字段 ) // updateMany更新全部匹配数据 db.user.updateMany( {age: {$gt:20}}, {$set: {status: 成年}} ) // $inc 数值自增 db.user.updateOne({name:张三}, {$inc:{age:1}}) // $push 数组追加元素 db.user.updateOne({name:张三}, {$push:{hobby:跑步}})4. 删除 deleteOne /deleteMany// 删除匹配第一条 db.user.deleteOne({name:张三}) // 删除所有匹配数据 db.user.deleteMany({age: {$lt:18}}) // 删除集合全部数据 db.user.deleteMany({})6.索引语法// 创建单字段索引 1升序 -1降序 db.user.createIndex({name:1}) // 复合索引 db.user.createIndex({name:1, age:-1}) // 唯一索引字段不能重复 db.user.createIndex({phone:1}, {unique:true}) // 查看集合所有索引 db.user.getIndexes() // 删除索引 db.user.dropIndex(name_1)7.聚合查询 aggregate复杂统计管道操作符$match过滤、$group分组、$sort、$limit// 统计不同年龄人数 db.user.aggregate([ // 过滤条件 {$match: {age: {$gte:18}}}, // 分组统计 {$group: { _id: $age, // 分组字段 total: {$sum: 1} // 计数 }}, // 排序 {$sort: {total:-1}} ])8.权限 / 用户管理// 切换到admin库 use admin // 创建管理员用户 db.createUser({ user: admin, pwd: 123456, roles: [root] }) // 创建test只有读权限对数据库testdb db.createUser({ user: test, pwd: 123456, roles: [{role:read,db:testdb}] }) // 查看所有用户 db.getUsers() // 删除用户 db.dropUser(admin)第二阶段: MongoDB进阶1.MongoDB 索引底层原理1. 索引是什么索引是集合文档中指定字段的有序映射表类似书本目录 无索引时查询是全集合扫描COLLSCAN逐条对比文档数据量大极慢 有索引时走索引扫描IXSCAN直接通过索引定位文档。查看: db.users.getIndexes()MongoDB 默认索引_id唯一索引自动创建不可删除。2. 底层存储结构 BTree内部节点只存 key不存储真实数据用来路由查找所有真实数据 / 记录指针只存放在叶子节点叶子节点形成有序双向链表范围查询极强。3. 索引分类底层逻辑1单字段索引db.user.createIndex({age:1})2复合索引(最左前缀匹配原则 查询条件必须优先使用索引最左侧的字段索引才能正常生效 一旦中间某个索引字段缺失、或者出现范围查询该字段右侧所有索引列失效。)db.user.createIndex({name:1,age:1})3唯一索引db.user.createIndex({phone:1},{unique:true})4稀疏索引 只存储存在该字段的文档缺失字段不进入索引节省空间。db.users.createIndex( {email:1}, {sparse:true} )5文本索引(专门用来全文关键词检索把字符串内容自动拆分成单词快速搜索包含某个词语的文档:::: 倒排索引)db.articles.createIndex({ content: text })(6) 地理索引4. 索引读写代价索引加速查询但降低写入性能插入 / 更新 / 删除文档时所有相关索引树必须同步修改索引越多写操作insert/update/delete开销越大索引占用磁盘内存索引过大无法放入内存时查询性能暴跌。5.索引执行计划判断索引是否生效explain(executionStats) 分析执行计划判断是否命中索引、扫描数据量、执行耗时// 查看查询执行详情 db.user.find({name:张三,age:22}).explain(executionStats)关键字段解读stage: COLLSCAN全表扫描无索引需要建索引stage: IXSCAN命中索引正常6.索引调优1.优先将等值条件放在复合索引前面范围条件放最后2.遵循最左前缀原则避免跳跃索引字段查询3.索引字段上不要使用函数运算4.控制索引数量索引越多写入压力越大。5.清理无效 / 长期不使用的索引第三阶段分布式集群高可用副本集分片集群1.副本集 Replica Set1. 副本集作用故障自动转移主节点宕机自动选新主业务无感知数据多副本持久化防止单盘 / 单节点丢失读写分离主写、从读分摊查询压力支持数据回滚、备份恢复。2. 副本集角色至少 3 节点标准架构1Primary 主节点唯一接收写操作的节点所有写入记录 oplog操作日志同步给从节点一个副本集同一时间只有 1 个主。2Secondary 从节点异步同步主节点 oplog保存完整数据副本不能写默认不提供读可开启 secondaryOk 实现读写分离主节点故障时参与投票选举新主。3Arbiter 仲裁节点可选不存数据只参与投票场景2 个数据节点时加 1 个仲裁凑奇数防止脑裂生产标准架构3 个数据节点1 主 2 从无需仲裁。3. 核心机制3.1 Oplog 同步日志Primary 收到写请求执行数据写入将本次写操作记录写入oplog.rsSecondary 节点持续异步拉取主节点最新 Oplog从节点串行重放日志保持数据和主节点同步从节点追不上主需重新全量同步3.2 自动选举高可用核心选举触发条件主节点心跳失联默认 10s 规则总投票节点必须是奇数避免平票脑裂候选节点必须拥有最新 oplog数据最新才能当选选举期间副本集只读持续几秒业务短暂不可写可配置优先级priority控制节点优先当选主。3.3 读写分离模式// mongosh 客户端设置读从节点 db.getMongo().setReadPref(secondaryPreferred)读策略primary只读主默认强一致primaryPreferred优先主主挂了读从secondary只读从适合报表、离线统计secondaryPreferred优先从无从再读主4. 副本集故障演示主节点宕机 → 2 个从节点检测心跳丢失发起选举数据最新从节点成为新主应用自动重连新主业务恢复写入旧主重启后自动变成从同步缺失 oplog。2.分片集群 Sharded Cluster分布式扩容当单副本集数据量 TB 级、单库性能瓶颈使用分片集群水平拆分数据。1. 分片集群四大组件1Shard 分片节点每一个 Shard 都是独立副本集自带高可用数据按分片键拆分分散存储在不同 shard示例shard1 (1 主 2 从)、shard2 (1 主 2 从)、shard3 (1 主 2 从)2mongos 路由节点无持久化数据内存进程接收客户端所有 CRUD 请求根据分片键路由请求到对应 shard聚合、跨分片查询由 mongos 汇总结果生产部署多个 mongos 做负载均衡防止单点故障。3Config Server 配置服务器存储集群元数据分片信息、分片键、集合路由规则、分片均衡器状态必须部署副本集3 节点保证元数据高可用mongos 启动时拉取配置元数据缓存本地。4Balancer 均衡器后台进程运行在 config 服务器自动监控分片数据块chunk分布 当分片数据差距过大自动迁移 chunk 到压力小的分片平衡数据。2. 分片核心概念分片键 Shard Key1Chunk 数据块MongoDB 将集合数据切分成固定大小 chunk默认 64MB每个 chunk 只属于一个 shard。2分片键作用指定集合内 1 个 / 多个字段作为拆分依据决定数据路由规则。 两种分片策略范围分片按字段数值区间划分 chunk 例user_id 1~10000 → shard110001~20000 → shard2 适合范围查询缺点热点写入自增 ID 全部写入同一个分片哈希分片对分片键哈希取模均匀打散数据到所有分片 解决自增 ID 热点写入但范围查询性能差3 分片键设计禁忌低区分度字段性别、状态不能做分片键频繁更新分片键字段会触发 chunk 迁移性能暴跌分片键一旦选定无法修改设计前必须评估业务3. 分片集群读写流程客户端连接 mongosmongos 向 config 拉取路由元数据根据查询条件 分片键判断数据在哪个 shard单分片查询直接下发对应 shard性能高跨分片查询mongos 向所有 shard 分发请求再聚合结果性能差插入 / 更新 / 删除文档时路由到对应 shard 副本集主节点balancer 后台自动均衡 chunk。4. 高可用保障机制每个 shard 是副本集单分片节点宕机自动选主数据不丢config 3 节点副本集元数据多副本元数据不丢失多 mongos 部署前端加负载均衡Nginx/LVS单个 mongos 挂了不影响业务chunk 迁移热迁移迁移过程不阻塞读写平衡数据无停机。3.常见常用运维命令1.副本集操作// 查看副本集状态 rs.status() // 查看配置 rs.conf() // 手动降级主节点主动切换主 rs.stepDown()2.分片集群操作mongos 中执行// 查看分片列表 sh.status() // 开启集合分片 sh.shardCollection(test.user, {shardKey: {userId: hashed}}) // 手动触发均衡 sh.startBalancer() // 查看chunk分布 db.user.getShardDistribution()第四阶段运维安全、性能调优、项目实战一、数据备份与恢复1.逻辑备份# 指定IP端口、账号密码、指定数据库 mongodump -h 127.0.0.1:27017 -u admin -p 123456 --authenticationDatabase admin -d testdb -o ./backup_test #--gzip压缩备份 # 只备份单个集合 mongodump -d testdb -c user -o ./backup_user2.逻辑恢复# 恢复指定数据库带认证 mongorestore -h 127.0.0.1:27017 -u admin -p 123456 --authenticationDatabase admin -d testdb ./backup_test/testdb # 恢复压缩包 mongorestore --host 127.0.0.1 --port 27017 -u admin -p 123456 --authenticationDatabase admin --gzip ./backup_gz3.物理备份直接复制数据目录/data/db到备份盘依赖 LVM 快照、云磁盘快照阿里云 / 腾讯云磁盘快照二、慢查询监控开启Profiler慢日志、分析慢查询、定位低效语句、优化SQL。三、存储引擎与参数调优WiredTiger默认存储引擎原理、缓存配置、内存优化、磁盘IO优化。四、Python pymongo实战第五阶段实操前置统一准备1. 安装 MongoDB 7.0 yum 源# 创建yum源文件 cat /etc/yum.repos.d/mongodb-org-7.0.repo EOF [mongodb-org-7.0] nameMongoDB Repository baseurlhttps://repo.mongodb.org/yum/redhat/9/mongodb-org/7.0/x86_64/ gpgcheck1 enabled1 gpgkeyhttps://www.mongodb.org/static/pgp/server-7.0.asc EOF # 安装 dnf install -y mongodb-org2. 关闭 SELinux、防火墙测试环境setenforce 0 sed -i s/^SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config systemctl stop firewalld systemctl disable firewalld3. 创建统一数据目录mkdir -p /data/mongo/{rs1,rs2,rs3,shard1a,shard1b,shard1c,shard2a,shard2b,shard2c,cfg1,cfg2,cfg3,mongos} chown -R mongod:mongod /data/mongo1.副本集ReplicaSet端口规划rs127017主节点候选rs227018rs3270191. 启动 3 个 mongod 实例副本集模式终端分别执行三条启动命令或写脚本# 节点1 mongod --replSet rs0 --bind_ip 0.0.0.0 --port 27017 --dbpath /data/mongo/rs1 --logpath /data/mongo/rs1/mongod.log --fork # 节点2 mongod --replSet rs0 --bind_ip 0.0.0.0 --port 27018 --dbpath /data/mongo/rs2 --logpath /data/mongo/rs2/mongod.log --fork # 节点3 mongod --replaSet rs0 --bind_ip 0.0.0.0 --port 27019 --dbpath /data/mongo/rs3 --logpath /data/mongo/rs3/mongod.log --fork2. 初始化副本集连接任意节点mongosh --port 27017执行初始化脚本使用本机 IP不要用 127.0.0.1后续分片集群也要复用将192.168.1.100替换为你 CentOS9 真实内网 IPrs.initiate({ _id: rs0, members: [ {_id:0, host:192.168.1.100:27017}, {_id:1, host:192.168.1.100:27018}, {_id:2, host:192.168.1.100:27019} ] }) // 查看状态 rs.status() rs.conf()等待几秒自动选举 primary。3.副本集停止命令mongosh --port 27017 --eval db.adminCommand({shutdown:1}) mongosh --port 27018 --eval db.adminCommand({shutdown:1}) mongosh --port 27019 --eval db.adminCommand({shutdown:1})⚠️ 重要提醒副本集完成测试后先关闭所有 mongod再部署分片集群端口不要冲突。如果想实现仲裁节点的话 直接加一个 arbiterOnly:true 参数即可参与选举、只投票、不存储业务数据rs.initiate({ _id:rs_arb, members:[ {_id:0, host:172.19.194.5:27020}, {_id:1, host:172.19.194.5:27021}, {_id:2, host:172.19.194.5:27022, arbiterOnly:true} ] })2.分片集群Sharded Cluster分片集群整体端口规划角色端口目录Shard1 副本集 shard-rs1-a28001/data/mongo/shard1aShard1 副本集 shard-rs1-b28002/data/mongo/shard1bShard1 副本集 shard-rs1-c28003/data/mongo/shard1cShard2 副本集 shard-rs2-a28011/data/mongo/shard2aShard2 副本集 shard-rs2-b28012/data/mongo/shard2bShard2 副本集 shard-rs2-c28013/data/mongo/shard2cConfig 副本集 cfg-rs-a29001/data/mongo/cfg1Config 副本集 cfg-rs-b29002/data/mongo/cfg2Config 副本集 cfg-rs-c29003/data/mongo/cfg3Mongos 路由30000无数据目录规则Config Server必须是副本集MongoDB5 强制要求每个 shard 推荐使用副本集生产标准架构所有实例必须使用内网 IP 通信禁止仅 127.0.0.1步骤 1启动 Config Server 副本集mongod --configsvr --replSet cfgrs --bind_ip 0.0.0.0 --port 29001 --dbpath /data/mongo/cfg1 --logpath /data/mongo/cfg1/mongod.log --fork mongod --configsvr --replSet cfgrs --bind_ip 0.0.0.0 --port 29002 --dbpath /data/mongo/cfg2 --logpath /data/mongo/cfg2/mongod.log --fork mongod --configsvr --replSet cfgrs --bind_ip 0.0.0.0 --port 29003 --dbpath /data/mongo/cfg3 --logpath /data/mongo/cfg3/mongod.log --fork初始化 config 副本集mongosh --port 29001rs.initiate({ _id:cfgrs, members:[ {_id:0,host:192.168.1.100:29001}, {_id:1,host:192.168.1.100:29002}, {_id:2,host:192.168.1.100:29003} ] }) rs.status()步骤 2启动 Shard1 副本集shardrs1mongod --shardsvr --replSet shardrs1 --bind_ip 0.0.0.0 --port 28001 --dbpath /data/mongo/shard1a --logpath /data/mongo/shard1a/mongod.log --fork mongod --shardsvr --replSet shardrs1 --bind_ip 0.0.0.0 --port 28002 --dbpath /data/mongo/shard1b --logpath /data/mongo/shard1b/mongod.log --fork mongod --shardsvr --replSet shardrs1 --bind_ip 0.0.0.0 --port 28003 --dbpath /data/mongo/shard1c --logpath /data/mongo/shard1c/mongod.log --fork初始化 shardrs1mongosh --port 28001rs.initiate({ _id:shardrs1, members:[ {_id:0,host:192.168.1.100:28001}, {_id:1,host:192.168.1.100:28002}, {_id:2,host:192.168.1.100:28003} ] })步骤 3启动 Shard2 副本集shardrs2mongod --shardsvr --replSet shardrs2 --bind_ip 0.0.0.0 --port 28011 --dbpath /data/mongo/shard2a --logpath /data/mongo/shard2a/mongod.log --fork mongod --shardsvr --replSet shardrs2 --bind_ip 0.0.0.0 --port 28012 --dbpath /data/mongo/shard2b --logpath /data/mongo/shard2b/mongod.log --fork mongod --shardsvr --replSet shardrs2 --bind_ip 0.0.0.0 --port 28013 --dbpath /data/mongo/shard2c --logpath /data/mongo/shard2c/mongod.log --fork初始化 shardrs2mongosh --port 28011rs.initiate({ _id:shardrs2, members:[ {_id:0,host:192.168.1.100:28011}, {_id:1,host:192.168.1.100:28012}, {_id:2,host:192.168.1.100:28013} ] })步骤 4启动 mongos 路由节点mongos 不需要 dbpath指定 config 副本集地址mongos --configdb cfgrs/192.168.1.100:29001,192.168.1.100:29002,192.168.1.100:29003 \ --bind_ip 0.0.0.0 --port 30000 \ --logpath /data/mongo/mongos/mongos.log --fork步骤 5连接 mongos添加分片节点mongosh --port 30000// 添加shard1副本集 sh.addShard(shardrs1/192.168.1.100:28001,192.168.1.100:28002,192.168.1.100:28003) // 添加shard2副本集 sh.addShard(shardrs2/192.168.1.100:28011,192.168.1.100:28012,192.168.1.100:28013) // 查看分片状态 sh.status()步骤 6开启数据库分片、指定片键测试// 开启数据库分片 sh.enableSharding(testdb) // 创建集合并分片以uid作为片键 sh.shardCollection(testdb.user, {uid:1})分片集群全部节点停止脚本# 关闭mongos mongosh --port 30000 --eval db.adminCommand({shutdown:1}) # 关闭shard1 mongosh --port 28001 --eval db.adminCommand({shutdown:1}) mongosh --port 28002 --eval db.adminCommand({shutdown:1}) mongosh --port 28003 --eval db.adminCommand({shutdown:1}) # 关闭shard2 mongosh --port 28011 --eval db.adminCommand({shutdown:1}) mongosh --port 28012 --eval db.adminCommand({shutdown:1}) mongosh --port 28013 --eval db.adminCommand({shutdown:1}) # 关闭config mongosh --port 29001 --eval db.adminCommand({shutdown:1}) mongosh --port 29002 --eval db.adminCommand({shutdown:1}) mongosh --port 29003 --eval db.adminCommand({shutdown:1})

相关新闻