Mongo 进阶 - WT 引擎:Page 生命周期 | Java 全栈知识体系

通过前文我们了解到数据以 page 为单位加载到 cache; 有必要系统的分析一页 page 的生命周期、状态以及相关参数的配置,这对后续 MongoDB 的性能调优和故障问题的定位和解决有帮助。@pdai

  为什么要了解 Page 生命周期


  通过前文我们了解到数据以 page 为单位加载到 cache、cache 里面又会生成各种不同类型的 page 及为不同类型的 page 分配不同大小的内存、eviction 触发机制和 reconcile 动作都发生在 page 上、page 大小持续增加时会被分割成多个小 page,所有这些操作都是围绕一个 page 来完成的。

  因此,有必要系统的分析一页 page 的生命周期、状态以及相关参数的配置,这对后续 MongoDB 的性能调优和故障问题的定位和解决有帮助。

  Page 的生命周期


  Page 的典型生命周期如下图所示:

  • 第一步:pages 从磁盘读到内存;
  • 第二步:pages 在内存中被修改;
  • 第三步:被修改的脏 pages 在内存被 reconcile,完成后将 discard 这些 pages。
  • 第四步:pages 被选中,加入淘汰队列,等待被 evict 线程淘汰出内存;
  • 第五步:evict 线程会将“干净“的 pages 直接从内存丢弃(因为相对于磁盘 page 来说没做任何修改),将经过 reconcile 处理后的磁盘映像写到磁盘再丢弃“脏的”pages。

  pages 的状态是在不断变化的,因此,对于读操作来说,它首先会检查 pages 的状态是否为 WT_REF_MEM​,然后设置一个 hazard 指针指向要读的 pages,如果刷新后,pages 的状态仍为 WT_REF_MEM,读操作才能继续处理。

  与此同时,evict 线程想要淘汰 pages 时,它会先锁住 pages,即将 pages 的状态设为 WT_REF_LOCKED​,然后检查 pages 上是否有读操作设置的 hazard 指针,如有,说明还有线程正在读这个 page 则停止 evict,重新将 page 的状态设置为 WT_REF_MEM​;如果没有,则 pages 被淘汰出去。

  Page 的各种状态


  针对一页 page 的每一种状态,详细描述如下:

  • WT_REF_DISK: 初始状态,page 在磁盘上的状态,必须被读到内存后才能使用,当 page 被 evict 后,状态也会被设置为这个。
  • WT_REF_DELETED: page 在磁盘上,但是已经从内存 B-Tree 上删除,当我们不在需要读某个 leaf page 时,可以将其删除。
  • WT_REF_LIMBO: page 的映像已经被加载到内存,但 page 上还有额外的修改数据在 lookasidetable 上没有被加载到内存。
  • WT_REF_LOOKASIDE: page 在磁盘上,但是在 lookasidetable 也有与此 page 相关的修改内容,在 page 可读之前,也需要加载这部分内容。

  当对一个 page 进行 reconcile 时,如果系统中还有之前的读操作正在访问此 page 上修改的数据,则会将这些数据保存到 lookasidetable;当 page 再被读时,可以利用 lookasidetable 中的数据重新构建内存 page。

  • WT_REF_LOCKED: 当 page 被 evict 时,会将 page 锁住,其它线程不可访问。
  • WT_REF_MEM: page 已经从磁盘读到内存,并且能正常访问。
  • WT_REF_READING: page 正在被某个线程从磁盘读到内存,其它的读线程等待它被读完,不需要重复去读。
  • WT_REF_SPLIT: 当 page 变得过大时,会被 split,状态设为 WT_REF_SPLIT,原来指向的 page 不再被使用。

  Page 的大小参数


  无论将数据从磁盘读到内存,还是从内存写到磁盘,都是以 page 为单位调度的,但是在磁盘上一个 page 到底多大?是否是最小分割单元?以及内存里面的各种 page 的大小对存储引擎的性能是否有影响?本节将围绕这些问题,分析与 page 大小相关的参数是如何影响存储引擎性能的。 总的来说,涉及到的关键参数和默认值如下表所示:

参数名称 默认配置值 含义
allocation_size 4KB 磁盘上最小分配单元
memory_page_max 5MB 内存中允许的最大 page 值
internal_page_max 4KB 磁盘上允许的最大 internal page 值
leaf_page_max 32KB 磁盘上允许的最大 leaf page 值
internal_key_max 1/10*internal_page internal page 上允许的最大 key 值
leaf_key_max 1/10*leaf_page leaf page 上允许的最大 key 值
leaf_key_value 1/2*leaf_page leaf page 上允许的最大 value 值
split_pct 75% reconciled 的 page 的分割百分比

  详细说明如下:

  • allocation_size

  MongoDB 磁盘文件的最小分配单元(由 WiredTiger 自带的块管理模块来分配),一个 page 的可以由一个或多个这样的单元组成;默认值是 4KB,与主机操作系统虚拟内存页的大小相当,大多数场景下不需要修改这个值。

  • memory_page_max

  WiredTigerCache 里面一个内存 page 随着不断插入修改等操作,允许增长达到的最大值,默认值为 5MB。当一个内存 page 达到这个最大值时,将会被 split 成较小的内存 pages 且通过 reconcile 将这些 pages 写到磁盘 pages,一旦完成写到磁盘,这些内存 pages 将从内存移除。

  需要注意的是:split 和 reconcile 这两个动作都需要获得 page 的排它锁,导致应用程序在此 page 上的其它写操作会等待,因此设置一个合理的最大值,对系统的性能也很关键。

  如果值太大,虽然 spilt 和 reconcile 发生的机率减少,但一旦发生这样的动作,持有排它锁的时间会较长,导致应用程序的插入或修改操作延迟增大;

  如果值太小,虽然单次持有排它锁的时间会较短,但是会导致 spilt 和 reconcile 发生的机率增加。

  • internal_page_max

  磁盘上 internalpage 的最大值,默认为 4KB。随着 reconcile 进行,internalpage 超过这个值时,会被 split 成多个 pages。

  这个值的大小会影响磁盘上 B-Tree 的深度和 internalpage 上 key 的数量,如果太大,则 internalpage 上的 key 的数量会很多,通过遍历定位到正确 leaf page 的时间会增加;如果太小,则 B-Tree 的深度会增加,也会影响定位到正确 leaf page 的时间。

  • leaf_page_max

  磁盘上 leaf page 的最大值,默认为 32KB。随着 reconcile 进行,leaf page 超过这个值时,会被 split 成多个 pages。

  这个值的大小会影响磁盘的 I/O 性能,因为我们在从磁盘读取数据时,总是期望一次 I/O 能多读取一点数据,所以希望把这个参数调大;但是太大,又会造成读写放大,因为读出来的很多数据可能后续都用不上。

  • internal_key_max

  internalpage 上允许的最大 key 值,默认大小为 internalpage 初始值的 1/10,如果超过这个值,将会额外存储。导致读取 key 时需要额外的磁盘 I/O。

  • leaf_key_max

  leaf page 上允许的最大 key 值,默认大小为 leaf page 初始值的 1/10,如果超过这个值,将会额外存储。导致读取 key 时需要额外的磁盘 I/O。

  • leaf_value_max

  leaf page 上允许的最大 value 值(保存真正的集合数据),默认大小为 leaf page 初始值的 1/2,如果超过这个值,将会额外存储。导致读取 value 时需要额外的磁盘 I/O。

  • split_pct

  内存里面将要被 reconciled 的 page 大小与 internal_page_max 或 leaf_page_max 值的百分比,默认值为 75%,如果内存里面被 reconciled 的 page 能够装进一个单独的磁盘 page 上,则不会发生 spilt,否则按照该百分比值*最大允许的 page 值分割新 page 的大小。

  Page 无锁及压缩


  https://blog.csdn.net/weixin_45583158/article/details/100143033

  参考文章


  • 文章来源在新窗口打开
  • 作者:郭远威
  • MongoDB 中文社区委员,长沙分会主席;《大数据存储 MongoDB 实战指南》作者资深大数据架构师,通信行业业务架构与数据迁移专家
  • 文章来源在新窗口打开
  • 袁荣喜,学霸君工程师,2015 年加入学霸君,负责学霸君的网络实时传输和分布式系统的架构设计和实现,专注于基础技术领域,在网络传输、数据库内核、分布式系统和并发编程方面有一定了解
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    91 引用 • 59 回帖 • 4 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    53 引用 • 190 回帖
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    118 引用 • 54 回帖
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    268 引用 • 666 回帖 • 1 关注
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    44 引用 • 208 回帖 • 1 关注
  • Unity

    Unity 是由 Unity Technologies 开发的一个让开发者可以轻松创建诸如 2D、3D 多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    25 引用 • 7 回帖 • 120 关注
  • AWS
    11 引用 • 28 回帖 • 8 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    693 引用 • 537 回帖
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    181 引用 • 400 回帖
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    209 引用 • 2040 回帖
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    93 引用 • 122 回帖 • 619 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 381 关注
  • Access
    1 引用 • 3 回帖 • 1 关注
  • 浅吟主题

    Jeffrey Chen 制作的思源笔记主题,项目仓库:https://github.com/TCOTC/Whisper

    1 引用 • 28 回帖 • 2 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    500 引用 • 1396 回帖 • 243 关注
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    34 引用 • 37 回帖 • 554 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    19 引用 • 23 回帖 • 738 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 2 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 645 关注
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    98 引用 • 367 回帖
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 444 关注
  • 音乐

    你听到信仰的声音了么?

    62 引用 • 512 回帖
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    29 引用 • 202 回帖 • 28 关注
  • 叶归
    12 引用 • 56 回帖 • 20 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 5 关注
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 144 关注