![Postgresql 的 ZFS 磁盘在写入密集型应用程序中会快速碎片化](https://linux22.com/image/777299/Postgresql%20%E7%9A%84%20ZFS%20%E7%A3%81%E7%9B%98%E5%9C%A8%E5%86%99%E5%85%A5%E5%AF%86%E9%9B%86%E5%9E%8B%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E4%B8%AD%E4%BC%9A%E5%BF%AB%E9%80%9F%E7%A2%8E%E7%89%87%E5%8C%96.png)
我正在运行一个写入密集型应用程序,其中我将 Postgresql 存储在 ZFS 上。通常,它运行良好,但我发现我的 ZFS 池碎片严重。我甚至创建了一个新的 ZFS 池并使用 zfs send / recv 将数据移到那里,以便对整个空间进行碎片整理并尝试一些可能限制碎片的新设置,但无济于事。
我不确定发生了什么。应用程序主要在进行更新,但 Postgres 应该能够重用磁盘上已有的空间(因为它会生成死元组并自动清理它们,它会重新使用这些页面)。我确实看到分配的空间基本保持不变,因此它不会增加磁盘使用率。但是,ZFS 的 COW 特性似乎使文件系统耗尽了可用空间并严重碎片化。
因此,经过大约 15 分钟的大量写入后,ZFS 池碎片从 0%(初始值)上升到 14%。这不应该是这样的:
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
postgres_data 149G 89.0G 60.0G - - 14% 59% 1.00x ONLINE -
postgres_wal 9.50G 289M 9.22G - - 0% 2% 1.00x ONLINE -
(注意:在我写这篇文章的时候,碎片化已经上升到了 16%。这里有些不对劲。)
关于我的实施的一些说明:
- 我将 WAL 放在一个单独的池中,理论上,对 WAL 的持续写入不会使主数据存储碎片化。显然,这行不通。
sync=disabled
我也曾尝试过根据 ZIL 会将我的磁盘变成瑞士奶酪的理论进行设置。同样没有任何效果。- 我目前使用
logbias=throughput
。我看到过关于此的相互矛盾的建议;官方文档建议对于 postgres 应该使用throughput
,而非常有用的指南说“logbias=throughput 会将写入池中的每个单个块碎片化。”因此,在我的初始池中(现在不再使用,因为它碎片化程度高达 80%),我最初使用了它,logbias=latency
但这显然也碎片化了整个磁盘。 - 我之所以使用是
ashift=9
因为物理磁盘(这是云存储)的块大小为 512。
我的完整 zfs 设置:
NAME PROPERTY VALUE SOURCE
postgres_data/data type filesystem -
postgres_data/data creation Tue May 17 23:36 2022 -
postgres_data/data used 88.9G -
postgres_data/data available 55.4G -
postgres_data/data referenced 88.9G -
postgres_data/data compressratio 1.98x -
postgres_data/data mounted yes -
postgres_data/data quota none default
postgres_data/data reservation none default
postgres_data/data recordsize 8K inherited from postgres_data
postgres_data/data mountpoint /var/lib/postgresql local
postgres_data/data sharenfs off default
postgres_data/data checksum on default
postgres_data/data compression zstd inherited from postgres_data
postgres_data/data atime off inherited from postgres_data
postgres_data/data devices on default
postgres_data/data exec on default
postgres_data/data setuid on default
postgres_data/data readonly off default
postgres_data/data zoned off default
postgres_data/data snapdir hidden default
postgres_data/data aclmode discard default
postgres_data/data aclinherit restricted default
postgres_data/data createtxg 619 -
postgres_data/data canmount on default
postgres_data/data xattr sa inherited from postgres_data
postgres_data/data copies 1 default
postgres_data/data version 5 -
postgres_data/data utf8only off -
postgres_data/data normalization none -
postgres_data/data casesensitivity sensitive -
postgres_data/data vscan off default
postgres_data/data nbmand off default
postgres_data/data sharesmb off default
postgres_data/data refquota none default
postgres_data/data refreservation none default
postgres_data/data guid 10551245409099064921 -
postgres_data/data primarycache all default
postgres_data/data secondarycache all default
postgres_data/data usedbysnapshots 0B -
postgres_data/data usedbydataset 88.9G -
postgres_data/data usedbychildren 0B -
postgres_data/data usedbyrefreservation 0B -
postgres_data/data logbias throughput local
postgres_data/data objsetid 595 -
postgres_data/data dedup off default
postgres_data/data mlslabel none default
postgres_data/data sync disabled local
postgres_data/data dnodesize legacy default
postgres_data/data refcompressratio 1.98x -
postgres_data/data written 88.9G -
postgres_data/data logicalused 176G -
postgres_data/data logicalreferenced 176G -
postgres_data/data volmode default default
postgres_data/data filesystem_limit none default
postgres_data/data snapshot_limit none default
postgres_data/data filesystem_count none default
postgres_data/data snapshot_count none default
postgres_data/data snapdev hidden default
postgres_data/data acltype off default
postgres_data/data context none default
postgres_data/data fscontext none default
postgres_data/data defcontext none default
postgres_data/data rootcontext none default
postgres_data/data relatime off default
postgres_data/data redundant_metadata most inherited from postgres_data
postgres_data/data overlay on default
postgres_data/data encryption off default
postgres_data/data keylocation none default
postgres_data/data keyformat none default
postgres_data/data pbkdf2iters 0 default
postgres_data/data special_small_blocks 0 default
答案1
碎片并不意味着你所想的那样。
它表示的是可用空间的碎片程度。它并不能显示实际数据的碎片程度。
实际上,除非您的空间真的很紧张或者遇到性能问题,否则不要担心这个值。
您应该撤消一些更改,因为它们可能会对您的实际工作量产生负面影响。
较小的 8k 记录大小也造成了这种情况(考虑默认的 128k 或者大于 8k 的值)
看:https://utcc.utoronto.ca/~cks/space/blog/solaris/ZFSZpoolFragmentationMeaning
看:https://bun.uptrace.dev/postgres/tuning-zfs-aws-ebs.html#zfs-recordsize