💈MongoDB 总结

type
Post
status
Published
date
Mar 1, 2025
slug
MongoDB
summary
category
技术分享
tags
mongoDB
icon
password
AI summary
Blocked by
Blocking
Category
 

MongoDB是什么

MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统,由 C++ 编写的。MongoDB 提供了 面向文档 的存储方式,操作起来比较简单和容易,支持“无模式”的数据建模,可以存储比较复杂的数据类型,是一款非常流行的 文档类型数据库
在高负载的情况下,MongoDB 天然支持水平扩展和高可用,可以很方便地添加更多的节点/实例,以保证服务性能和可用性。在许多场景下,MongoDB 可以用于代替传统的关系型数据库或键/值存储方式,皆在为 Web 应用提供可扩展的高可用高性能数据存储解决方案。
 

MongoDB的存储结构

  • 文档(Document):MongoDB 中最基本的单元,由 BSON 键值对(key-value)组成,类似于关系型数据库中的行(Row)。
  • 集合(Collection):一个集合可以包含多个文档,类似于关系型数据库中的表(Table)。
  • 数据库(Database):一个数据库中可以包含多个集合,可以在 MongoDB 中创建多个数据库,类似于关系型数据库中的数据库(Database)。

SQL 与 MongoDB 常见术语对比

SQL
MongoDB
表(Table)
集合(Collection)
行(Row)
文档(Document)
列(Col)
字段(Field)
主键(Primary Key)
对象 ID(Objectid)
索引(Index)
索引(Index)
嵌套表(Embedded Table)
嵌入式文档(Embedded Document)
数组(Array)
数组(Array)

MongoDB的存储引擎

查看引擎
MongoDB的存储引擎有很多种,WiredTiger 是目前最常用的(默认)存储引擎,提供了高性能、压缩和事务支持。
  • 支持文档级别的并发控制(Document-Level Concurrency),允许多个操作同时修改集合中的不同文档,提高了并发性能。
  • 支持压缩(Compression),可以减少磁盘空间占用,支持 Snappy 和 Zlib 压缩算法。
  • 支持高效的缓存管理,使用内存缓存(Cache)来加速数据访问。
  • 支持事务(Transactions),从 MongoDB 4.0 开始支持多文档事务。
 

简单使用

使用docker-compose 搭建环境

 
 
 
notion image
 

基础的增删改查

  • 创建集合db.createCollection("collectionName")
  • 插入数据db.collectionName.insertOne() 或 db.collectionName.insertMany()
  • 查询数据db.collectionName.find()
  • 更新数据:db.collection.updateOne(filter, update, options)db.collection.updateMany(filter, update, options)
    • filter:用于查找文档的查询条件。
    • update:指定更新操作的文档或更新操作符。
    • options:可选参数对象,如 upsertarrayFilters 等
  • 删除数据db.collectionName.deleteOne() 或 db.collectionName.deleteMany()
  • 删除集合db.collectionName.drop()
  • sort表示排序,1标识升序,-1标识降序
 
 
 

MongoDB的聚合操作

由多个阶段组成,每个阶段在文档通过管道时转换文档。每个阶段接收前一个阶段的输出,进一步处理数据,并将其作为输入数据发送到下一个阶段。
notion image

常用阶段操作符

操作符
简述
$match
匹配操作符,用于对文档集合进行筛选
$project
投射操作符,用于重构每一个文档的字段,可以提取字段,重命名字段,甚至可以对原有字段进行操作后新增字段
$sort
排序操作符,用于根据一个或多个字段对文档进行排序
$limit
限制操作符,用于限制返回文档的数量
$skip
跳过操作符,用于跳过指定数量的文档
$count
统计操作符,用于统计文档的数量
$group
分组操作符,用于对文档集合进行分组
$unwind
拆分操作符,用于将数组中的每一个值拆分为单独的文档
$lookup
连接操作符,用于连接同一个数据库中另一个集合,并获取指定的文档,类似于 populate

语法格式

 

实例

group 分组查询

 

bucket 同组数据汇聚

unwind 将数组展开

lookup实现关联查询

也可以搭配$unwind将userOrders数组拆分

MongoDB 架构

Master-Slave

Master-Slave 由主从角色构成:
Master ( 主 )
可读可写,当数据有修改的时候,会将 Oplog 同步到所有连接的Salve 上去
Slave ( 从 )
只读,所有的 Slave 从 Master 同步数据,从节点与从节点之间不感知
notion image
 

Replica Set(副本集模式)

  • 数据多副本,在故障的时候,可以使用完的副本恢复服务。注意:这里是故障自动恢复
  • 读写分离,读的请求分流到副本上,减轻主(Primary)的读压力;
  • 节点直接互有心跳,可以感知集群的整体状态;
    • notion image

一、拓扑感知过程 (Topology Discovery)

初始发现:
  1. 种子连接:驱动程序从连接字符串获取种子节点地址
  1. hello 命令:连接任意种子节点,发送 hello 命令获取集群信息
  1. 拓扑构建:根据返回的成员列表、主节点信息等,在内存中构建完整拓扑视图
持续监控:
  • 驱动程序定期向所有节点发送心跳检测
  • 实时感知节点状态变化、故障转移等事件
  • 动态更新内存中的拓扑视图,确保请求路由准确

二、读写流程

写操作流程:
  1. 应用程序发起写请求
  1. 驱动程序查询拓扑视图,定位当前 Primary 节点
  1. 写请求直接发送到 Primary 节点
  1. Primary 执行写操作并记录到 Oplog
  1. Secondary 节点异步从 Oplog 复制数据
  1. Primary 根据写策略返回确认
读操作流程(读写分离示例):
  1. 应用程序发起读请求,指定读偏好为 secondary
  1. 驱动程序从健康的 Secondary 节点中选择一个(通常选择延迟最低的)
  1. 读请求直接发送到选中的 Secondary 节点
  1. Secondary 节点执行查询并返回结果
  1. 驱动程序将结果返回给应用程序
核心特点:
  • 写操作必须经过 Primary 节点,保证强一致性
  • 读操作可根据读偏好策略灵活选择节点
  • 从 Secondary 读取可分担主节点压力,但可能存在数据延迟
  • 整个过程由客户端驱动程序自主完成,无需外部中间件
 

Sharding

notion image
MongoDB 的 sharding 是一种水平扩展方法,允许跨多台机器分布数据。sharding 架构由以下几个组件组成:
  • mongos: 这是查询路由器,充当应用程序和分片集群之间的接口。客户端连接到 mongos,而不是直接连接到各个分片
  • Config Servers
    • config Servers 维护着集群元数据,包括 Chunk 到 Shard 的映射关系
    • 这些映射存储在 Config Server 的 config.chunks 集合中
    • 每个 Chunk 记录包含其范围(minmax值)和所属的 Shard ID
  • Shard: 每个 shard 是存储部分数据的独立 MongoDB 实例或 replica set。实际数据存储在这里
  • 分片键(Shard Key): 用于在分片间分配数据的字段。MongoDB 使用分片键决定数据属于哪个分片。
 

工作原理

  • 数据分区: 基于分片键,将集合拆分为块(chunks)。
  • 分布式查询: mongos 会将查询路由到适当的分片。
  • 负载平衡: MongoDB 自动在分片之间平衡数据,确保数据均匀分布。
  • 自动故障转移: 每个分片通常是一个 replica set,提供高可用性。

拓扑感知过程

mongos 的拓扑感知:
  1. 启动初始化:mongos 从配置中获取 Config Servers 地址
  1. 元数据同步:连接 Config Servers,获取完整的集群元数据
      • Shard 列表和状态
      • 数据库和集合的分片配置
      • Chunk 分布映射(config.chunks 集合)
  1. 缓存构建:在内存中构建路由表缓存
  1. 持续更新:定期从 Config Servers 刷新元数据,保持路由信息最新
应用程序的连接:
  • 应用程序只需连接 mongos,无需了解底层 shard 分布
  • 驱动程序将 mongos 视为普通 MongoDB 实例进行连接
写操作流程:
  1. 应用请求:应用程序向 mongos 发送写请求
  1. 路由计算:mongos 根据 shard key 值计算目标 chunk
  1. shard 定位:查询路由表确定 chunk 所在的 shard
  1. 请求转发:mongos 将写请求转发到目标 shard
  1. shard 执行:目标 shard(通常是 replica set 的 primary)执行写操作
  1. 结果返回:shard 将执行结果返回给 mongos,mongos 再返回给应用程序
读操作流程:
单 shard 查询:
  1. mongos 根据查询条件中的 shard key 确定目标 shard
  1. 将查询直接路由到对应 shard
  1. shard 执行查询并返回结果
多 shard 查询(scatter-gather):
  1. mongos 识别查询需要访问多个 shard
  1. 并行向相关 shard 发送查询请求
  1. 收集各 shard 的结果
  1. 在 mongos 层面进行结果合并、排序等处理
  1. 返回最终结果给应用程序
 
 

Sharding 与 Replica Sets 对比

相似点
  • 都提供高可用性和故障转移功能
  • 都支持自动恢复
  • 都使用 MongoDB 的原生复制机制
区别
特性
Sharding
Replica Sets
主要目的
水平扩展,提高性能和存储容量
数据冗余和高可用性
数据分布
数据分布在多个分片上
完整数据集复制到所有节点
扩展方式
水平扩展(更多机器)
主要是垂直扩展(更好的硬件)
架构复杂性
较复杂,需要维护更多组件
相对简单
适用场景
大数据量,高并发
中小规模数据,需要冗余
查询路由
通过 mongos 路由
直接连接到 primary 或 secondary
管理开销
较高
较低

MongoDB的事物

MongoDB 事务遵循 ACID 属性(原子性、一致性、隔离性和持久性),允许对多个文档的操作作为一个单元执行,要么全部成功,要么全部失败。

支持的操作

事务中支持以下操作:
  • CRUD 操作 (创建、读取、更新、删除)
  • 批量写入操作
  • 查找和修改操作

不支持的操作

事务中不支持:
  • 创建/删除集合
  • 创建/删除索引
  • 删除数据库
  • 聚合 $out 和 $merge 阶段

事务配置参数

读关注 (Read Concern)

定义事务中读操作返回的数据的一致性级别:
  • "local": 返回最新的数据,无需确认是否已被多数节点确认
  • "majority": 返回已被大多数节点确认的数据
  • "snapshot": 返回同一时间点的多文档快照(事务中推荐)

写关注 (Write Concern)

定义写操作的确认要求:
  • { w: 1 }: 主节点确认
  • { w: "majority" }: 大多数节点确认(事务中推荐)
  • { j: true }: 写入操作必须写入到磁盘日志

读偏好 (Read Preference)

定义从哪些节点读取数据:
  • "primary": 从主节点读取(事务中必须)
 

事务限制与最佳实践

限制

  1. 时间限制: 事务必须在 60 秒内完成(可配置但不推荐超过默认值)
  1. 大小限制: 单个事务中的操作不能超过 16MB
  1. 资源锁: 过长的事务可能会导致资源锁定
  1. 性能影响: 事务会对性能产生一定影响

最佳实践

  1. 保持事务简短: 尽量减少事务中的操作数量和持续时间
  1. 避免大事务: 不要在一个事务中处理太多文档
  1. 合理设置超时: 根据业务需求设置适当的超时时间
  1. 异常处理: 始终包含错误处理和回滚逻辑
  1. 会话复用: 在可能的情况下复用会话以提高性能
  1. 索引优化: 确保事务中使用的查询有适当的索引支持
 

MongoDB的索引

查看索引
创建索引
删除索引

使用Golang SDK

 
code

需要注意的点

查询时

处理 mongo.ErrNoDocuments 错误,表示没有找到文档

更新时

使用$set 更新指定字段,避免覆盖整个文档
 
Replica
 

Reference

 
 
Prev
mac VMware Fusion 虚拟机安装
Next
K8s网络深度解析:CNI、VXLAN与主流插件的实现差异
Loading...
Article List
如果去做,还有一丝希望;但是不去做,就毫无希望
个人总结
技术分享
LLM
k8s
knative
agentic
istio
HAMI
Golang
转发
计算机网络
Redis
MySQL
Mysql