通过前文我们了解到数据以 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 年加入学霸君,负责学霸君的网络实时传输和分布式系统的架构设计和实现,专注于基础技术领域,在网络传输、数据库内核、分布式系统和并发编程方面有一定了解
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于