MongoDB-4 概述

概述

  • MongoDB是一个文档型数据库,MongoDB 以 JSON-like 格式(BSON) 存储数据。没有表、模式、SQL或行的概念。
  • 支持副本和分片实现靠扩展性
    • 分片(Sharding):水平拆分数据,支持海量数据存储和高并发访问。
    • 副本集(Replica Set):自动故障转移,保障高可用性(通常 3 节点起步)

数据格式示例

{
  "_id": "12345",
  "name": "张三",
  "age": 30,
  "address": {
    "city": "北京",
    "street": "中关村"
  },
  "hobbies": ["编程", "篮球"]
}

文档

  • 文档是MongoDB中的一个存储单元,由任意数目的键和值组成。相当于传统数据库中的行的概念
  • MongoDB要求每个文档必须有唯一标识符,_id,除非为该字段指定某个值,否则MongoDB将自动创建唯一值,默认_id格式是一个Objectld,它是个12字节的唯一标识符
  • MongoDB不要求每个文档必须含有相同的字段,也不要求同名的字段有相同类型的值

集合

  • 在 MongoDB 中,集合类似于关系型数据库中的表,但具有更灵活的结构。集合用于存储文档
  • MongoDB 使用集合对文档进行分组,
  • 同一个集合中的文档可以有不同的字段,无需预先定义结构。例如:如下两个文档可以存储在一个集合中,但是这两个文档的结构却不相同
// 文档1(包含 name 和 age)
{ "_id": 1, "name": "张三", "age": 25 }

// 文档2(包含 name 和 email,没有 age)
{ "_id": 2, "name": "李四", "email": "lisi@example.com" }

数据库

  • MongoDB 使用数据库对集合进行分组。
  • 一个 MongoDB 实例可以承载多个数据库,每个数据库有零个或多个集合。
  • 推荐的做法是将单个应用程序的所有数据都存储在同一个数据库中。
  • 通过将数据库名称与该库中的集合名称连接起来,可以获得一个完全限定的集合名称,称为命名空间。

admin

  • admin 数据库会在身份验证和授权时被使用。几乎所有全局管理命令都必须针对admin数据库来运行(例如:shutdownServer、listDatabases、rs.status()、addShard)

local

  • mongodb单个实例的数据会存储在此数据库中。
  • local 用于存储复制过程中所使用的数据,例如 oplog.rs(操作日志、replset.election集合存储了与选举相关的数据。
  • local 数据库本身不会被复制到其他节点中

config

  • config 数据库存储关于每个分片的信息。
  • config数据库专门由配置服务器(Config Servers)存储。
  • mongos(查询路由器)靠它来知道数据在哪

mongodb数据类型

null、布尔值、字符串、数组、内嵌文档(文档里面套文档)
数值

shell 默认使用 64 位的浮点数来表示数值类型。因此,下面的数值在 shell 中看起来是
“正常”的:
{"x" : 3.14}
{"x" : 3}
对于整数,可以使用 NumberInt 或 NumberLong 类,它们分别表示 4 字节和 8 字节的有符
号整数。
{"x" : NumberInt("3")}
{"x" : NumberLong("3")}

日期

MongoDB 会将日期存储为 64 位整数,表示自 Unix 纪元(1970 年 1 月 1 日)以来的毫
秒数,不包含时区信息。
{"x" : new Date()}

正则表达式

查询时可以使用正则表达式,语法与 JavaScript 的正则表达式语法相同。
{"x" : /foobar/i}

ObjectID

Object ID 是一个 12 字节的 ID,是文档的唯一标识。
{"x" : ObjectId()}

条件操作符

2270526-20220906212848971-56523476

oplog详解

oplog 存储位置

  • MongoDB 的 oplog(操作日志)存储在 磁盘 上,而不是内存中。

物理存储:

  • oplog 实际上是 local 数据库中的一个特殊 capped collection(固定大小集合)
  • 数据持久化存储在磁盘的数据文件中(通常位于 local/oplog.rs 集合)
  • 默认存储在 local 数据库对应的数据文件中

内存缓存:

  • 为提高性能,MongoDB 会缓存部分活跃的 oplog 条目在内存中(通过 WiredTiger 存储引擎的缓存机制)
  • 但这只是性能优化,oplog 的权威数据始终在磁盘上
  • 如果系统内存不足,可能影响 oplog 的缓存效果,但不会导致 oplog 数据丢失,只是性能下降
  • 写入先进入内存缓冲区,然后定期刷写到磁盘(默认60秒间隔,或每100MB写入)
  • 频繁访问的 oplog 条目会被缓存到内存。这显著提高了副本集成员同步的速度

查看 oplog 信息

  • 查看 oplog 大小和状态:
rs.printReplicationInfo()

输出示例:
configured oplog size:   1024MB
oplog first event time:  Thu Oct 05 2023 10:00:00 GMT+0800 (CST)
oplog last event time:   Thu Oct 05 2023 16:00:00 GMT+0800 (CST)
  • 直接查询 oplog 集合:
use local
db.oplog.rs.find().limit(1)

oplog配置建议

  • 对于高写入负载的系统,oplog 应足够大(通常建议能保存两到三天的操作)
  • 默认的 oplog 大小(空闲磁盘空间的5%)可能不适合生产环境
# 启动时指定 oplog 大小(MB)
mongod --replSet myReplSet --oplogSize 2048

# 或运行时调整:
db.adminCommand({replSetResizeOplog: 1, size: 1024*1024*1024}) // 1GB

选举详解

MongoDB 副本集中节点成为主节点(Primary)的资格条件

  • 在 MongoDB 副本集中,一个节点要成为主节点,必须满足以下条件:
    • 必须是数据节点(不能是仲裁者或隐藏节点)
    • 优先级(priority)大于0(默认所有数据节点priority=1)
    • 状态必须为"SECONDARY"(运行正常的从节点)
    • 拥有最新的数据集(与大多数节点同步)

选举过程中的评估标准

  • 当触发选举时,候选节点还需满足:

oplog足够新:

  • 候选节点的oplog必须比其他大多数节点的oplog更新或同等新
  • 通过比较optime(操作时间戳)判断

与多数节点连通:

  • 能与副本集中大多数节点建立连接
  • 包括仲裁者(仲裁者也参与投票)

未被禁止选举:

  • 没有被配置为priority: 0(永远不能成为主节点)
  • 没有被设置为hidden: true(隐藏节点)

选举权重因素

  • 当多个节点符合基本条件时,按以下顺序决定:
    • 优先级(priority)值(数值越高越优先)
    • optime新旧(操作日志越新越优先)
    • 节点_id值(数字越小越优先,作为最后比较条件)

回滚

什么是回滚

  • 当 MongoDB 副本集发生主节点切换时,原主节点上已写入但未同步到多数从节点的操作会被撤销,这个过程称为回滚(Rollback)。

触发回滚的条件

主节点宕机后重新加入副本集
网络分区导致原主节点失去多数连接
人工强制切换主节点(rs.stepDown())
原主节点上有未被多数从节点复制的写操作

回滚过程

节点检测到自己需要回滚(状态变为ROLLBACK)
确定需要回滚的操作点(lastOpTime和commonPoint)
撤销未被复制的写操作
从当前主节点重新同步数据
完成后重新加入副本集作为从节点

回滚数据保存

MongoDB 会将回滚的数据保存为 BSON 文件:

<dbpath>/rollback/
  ├── <collection>.<timestamp>.0.bson
  ├── <collection>.<timestamp>.1.bson
  └── ...

查看回滚信息

javascript
// 检查是否有待处理的回滚数据
db.adminCommand({getCmdLineOpts: 1}).parsed.storage.dbPath + "/rollback"

// 查看回滚状态
rs.status().members.filter(m => m.stateStr === "ROLLBACK")

减少回滚风险的方法

写关注(Write Concern)使用"majority"

javascript
db.products.insert(
  { item: "card", qty: 15 },
  { writeConcern: { w: "majority" } }
)

配置更大的oplog窗口

javascript
db.adminCommand({replSetResizeOplog: 1, size: 1024*1024*1024}) // 1GB
监控复制延迟

javascript
rs.printSlaveReplicationInfo()
避免长时间的网络分区

处理回滚数据

使用mongorestore恢复回滚数据:

bash
mongorestore --db dbname /data/db/rollback/{collection}.{timestamp}.bson
手动审查并重新应用重要操作

重要注意事项

回滚可能导致数据丢失(未被复制的操作)
回滚操作是自动进行的,无需人工干预
大事务可能导致长时间回滚
频繁回滚可能表明系统配置有问题

posted @ 2026-03-27 11:26  立勋  阅读(5)  评论(0)    收藏  举报