什么是WiredTiger?

MongoDB和 WiredTiger的职责范围

image.png

  • MongoDB使用的底层存储引擎
  • WT是键/值数据库,而不是文档数据库
  • 支持事务
  • 使用无锁算法
  • 压缩磁盘上的数据
  • 使用WT缓存和FS缓存
  • 支持多版本控制

image.png

  • 它将 BSON文档存储在BTree中
  • 通过内部键索引文档
  • 文档存储在叶节点中
  • 索引也是由索引值构成的B树

image.png

  • MongoDB数据存放在WT Table 中(collection-xxx.wt)
  • MongoDB索引也存放在WT Table 中(index-xxx.wt)

除此之外还有一些WT Table 用于存放元数据:

  • WiredTiger.wt: WiredTiger自己使用的元数据
  • _mdb_catalog.wt: MongoDB表定义等元数据
  • sizeStorer.wt:数据大小,条数等元数据

Journaling和Checkpoints

  • WiredTiger使用Journaling (预写日志)和Checkpoints(检查点)来确保数据在服务器发生故障时是持久化且可恢复的
  • Journaling是一种预写日志,其中最后一个检查点之后的更改以简单、可重放的形式保存到磁盘。
  • Checkpoint每分钟发生一次,以确保磁盘上始终存在完全一致的数据。恢复需要在最新检查点上重放最多一分钟的日志。

数据库中的缓存

  • WiredTiger有一块缓存
    • 默认大小是(RAM - 1GB)的一半或256MB,取较大值。
    • 除非在同一台服务器上运行多个实例,否则不应更改此设置·缓存中的数据块可以在需要时保留文档的多个版本
  • 不再使用时,未使用的块将从缓存中清除
  • 如果当majority无法满足,数据将写入称为LAS文件的缓存文件
  • 当需要空间时,不常用的数据将从缓存中逐出
  • 缓存中的块可以来自集合或索引

触发缓存驱逐的阈值

  • Read cache
    • 80%以下没有驱逐缓存政策
    • 80+%开始使用后台线程驱逐缓存
    • 95+%开始使用应用程序线程进行主动驱逐。
    • 100%阻止新的操作,直到发生一些驱逐
  • Dirty cache
    • 5%以下无缓存处理。
    • 5+%开始使用后台线程
    • 20+%开始使用应用程序线程来提供帮助

合理的缓存大小

  • 不能依赖Pagefault,需要结合查看iostats 和serverStatus()指标:
    • 磁盘读取
    • 磁盘写入。字节读入缓存
    • 从缓存中写入的字节
  • 如果磁盘低读磁盘+高数据读入缓存
    • 增加WT缓存大小
  • 如果中到高读磁盘+中到高数据读入缓存
    • 添加内存

WiredTiger的读写过程

  • 所有数据库块都通过WiredTiger缓存读取和写入
  • 何时需要将数据读入WiredTiger缓存
    • MongoDB将只会读入它需要的数据块

image.png

WiredTiger 压缩

  • 使用WiredTiger,默认情况下为集合和索引启用压缩
  • 压缩有助于最大限度地减少存储使用,但需要更多CPU计算
  • 数据库块(页面)在磁盘和系统缓存中被压缩,但在 WiredTiger缓存中未压缩o
    • Snappy(默认)、Zlib、Zstd、未压缩
    • 为什么你会选择不同的压缩方式?
  • 索引在RAM和磁盘上都被压缩
    • 索引压缩使用前缀压缩
    • 每个条目都存储为已经出现过条目的增量

WiredTiger并发

  • WiredTiger对写操作使用文档级并发控制
  • 写入操作永远不会阻止其他线程读取数据
  • 写入只会短暂地阻止其他线程写入相同的文档
  • 表或数据库级别的锁定很少见
    • 某些维护操作可能会锁定数据库或集合
  • 客户端试图同时更改同一份数据时
    • 从技术上讲,两者都在缓存中创建了一个新版本,但较晚完成的版本需要基于已经完成的版本重新开始
    • 这实际上导致写入形成一个队列

WriteConcern写关注

当你写入复制集时:

  1. 如何保证持久化?
  2. 如果主节点的最新数据在宕机后回滚,会发生什么?谁来决定哪些数据不能丢失?

数据复制过程

  1. 应用程序将所有更新写入到主节点
  2. 主节点在时间T应用变更,并将变更记录放在操作日志(Oplog)中
  3. 从节点观察Oplog并将读取到时间T的变更
  4. 从节点将到时间T的更新记录应用于自己本身
  5. 从节点将变更记录记录在自己的Oplog中
  6. 从节点继续请求时间T之后的数据
  7. 主节点知道每个从节点最新的时间T的记录.

image.png

数据写入过程

image.png

写关注级别

  • MongoDB中允许你定义'OK, committed"的级别。
    • 由主节点通过网络接收,但未写检查确认(w :O)
    • 由主节点接收和写入-持久化到主节点的磁盘(w :1, j : 1)。
    • 由大多数节点接收和写入( w : "majority") w是服务器数量,j是否等待下一次磁盘刷新(默认为大多数)

你可以在应用程序中的任何写入,连接或用于写入的对象上指定这些

MongoDB将等到它达到你请求的级别或者超时时间.如果它超时,它可能仍然完成了其中的一部分.如果发生超时,你可能需要确认状态

image.png

Read preference读偏好

根据场景需求选择合适的读偏好

  • 仅从主节点读
  • 优先从从主节点读,除非不存在主节点(primaryPreferred)
  • 仅从从节点读取
  • 优先从从节点读,除非不存在从节点.
  • 从最近的地理位置的节点上读
  • 从一组指定的节点上读