第七章:缓存

与任何其他文件系统一样,ZFS使用内存缓存来提高性能。不过,与大多数其他文件系统不同,系统管理员可以调整这些缓存以调整系统行为。ZFS在 zpool.cache 文件中缓存系统池列表。它可以使用缓存设备进行读写。不过,最明显的缓存是ZFS的自适应替换缓存(Adaptive Replacement Cache,ARC)。

第七章:缓存自适应替换缓存传统缓冲区缓存ARC 设计ARC 内存使用zfs-stats修改 ARC限制 ARC 大小元数据和 ARC数据集和 ARCLevel 2 ARC(二级ARC)L2ARC 内存使用L2ARC 缓存流播文件L2ARC 写入速度ZFS 意图日志——ZIL同步和异步事务ZFS 意图日志单独意图日志每个数据集ZIL调优通过堆栈进行同步写入zpool.cache

自适应替换缓存

从内存调用数据比从磁盘访问文件快得多。类Unix操作系统通常将最近访问的文件的副本保留在内存缓冲区缓存中。ZFS使用更复杂和更有效的缓存类型,即自适应替换缓存(Adaptive Replacement Cache,ARC)。理解ARC始于理解缓冲区缓存(buffer cache)。

传统缓冲区缓存

缓冲区缓存基于最近最少使用(Least Recently Used,LRU)算法选择要缓存的数据。LRU是一个列表,存储在上次访问数据块时。每当使用对象时,它都会移动到列表的顶部。当缓存填满时,系统将从列表底部删除项,直到有足够的空间在列表顶部插入新项。

缓冲区缓存工作良好,足以提供性能提升,但在某些情况下,LRU方法会导致不期望的行为。考虑夜间备份。备份程序扫描整个硬盘驱动器,查找自上次备份以来修改的文件。运行此扫描会将系统上的每个文件添加到列表的顶部,使刚刚扫描的文件从底部落下。在备份结束时,缓冲区缓存中充满了无人关心的数据。与此同时,任务关键型数据库已完全推送到磁盘上。这称为缓存抖动(cache thrashing)。

ARC避免了这些问题。

ARC 设计

ARC还缓存最近从磁盘读取的文件。ARC有两对列表,而不是一个列表。

添加MFU列表可以减少缓存抖动过程(如假设的备份作业)的影响。扫描系统上的每个文件时,会清除MRU列表,但不会影响MFU列表。出于备份目的扫描一次块并不“频繁”。最常用的文件仍缓存在内存中。运行备份仍然会影响磁盘I/O,从而降低写入性能,但系统会从内存中的副本中提供最常用的文件。

每个列表都与一个 ghost 列表配对,其中包含有关已从列表中删除的块的信息。当MRU或MFU列表填满时,列表底部的块会脱落。通过跟踪从缓存中掉落的这些块,ARC可以防止块不断循环进入缓存。ARC还可以决定一个区块现在是否被频繁使用,以保证进入MFU列表。

几乎所有情况下,ARC都是自调整的,系统管理员的手动调整只会损害系统。假如有特定应用程序需要特殊处理,在开始摆弄ARC之前,应先了解它的行为。

ARC 内存使用

ARC被设计为既贪婪又慷慨。如果系统有空闲内存,并且ARC认为它可能会从中受益,则ARC会认领(claims)该内存。每次系统从磁盘读取内容时,ARC都会将文件缓存在内存中。ARC继续缓存文件,直到系统使用其所有内存。

FreeBSD为内核和应用程序保留1 GB的RAM。对于ARC来说,系统内存的所有其余部分都是公平的。在具有大量存储而没有大量内存的长时间运行的系统上,看到ARC占用大部分系统内存并不奇怪。

然而,ARC对内存请求的优先级非常低。如果应用程序请求内存,但系统没有空闲内存,则内核会缩小ARC,为应用程序提供其请求的内存。将存储器作为自由成员从ARC返回到系统的过程不是瞬时的;这可能需要几秒钟。

因此:如果内存是空闲的,ARC将使用它。如果某个东西需要该内存,ARC会将其返还。现代服务器有大量内存。他们还不如用它做点什么。Free RAM is wasted RAM(内存空闲就是浪费),这句老话仍然适用。

检查ARC大小最简单的方法就是使用 top(1) 命令。以下是一个具有32GB内存和20TB磁盘的文件服务器的 top 输出片段:

Mem 行出现在几乎所有类Unix系统的top输出中,并提供了系统用于各种任务的内存量的详细信息。虽然ARC是存储器的一个子集,但它是单独出现的,因此可以提供更多细节。

虽然ARC对内存很贪婪,但请注意,这个长时间运行的系统仍然有几GB的可用内存。磁盘已满,但实际用户所需的数据量相对较小,任何管理过文件服务器的人都会认识到这种模式——每个企业的会计部门都有一个主电子表格,加上来自不同日期的15万亿(bajillion)个略有不同的电子表格副本,所有这些都是至关重要的,必须永远保留给后代。如果ARC正使用系统的大部分内存,那是因为一个进程访问了一个文件。ARC不会找借口滥用RAM。

zfs-stats

FreeBSD通过 vfs.zfskstat.zfs 的各种 sysctls 公开ZFS性能、设置和指标。这些值本身通常意义不大,但相互比较时具有启发性。强烈建议使用 zfs-stats 包检查ARC,而不是直接解析这些值。

使用zfs-stats -A 获取ARC的基本信息,比如当前大小和ARC中每个队列的大小。下面是Lucas系统之一的 zfs-stats 报告中有趣的片段。

Memort Throttle Count(内存节流计数)告诉我们ARC收缩(shrunk)了多少次,以便将内存退回给内核供其他进程使用。如果内存节流计数很高,可以考虑降低ARC大小的限制,以确保有足够的可用内存用于其他进程。不过,ARC内存调节并不意味着系统必须有更多的内存,而只是意味着它会使用额外的内存。

这个特殊的ARC是其最大大小的36.22%,即10.89GB。它被配置为最大大小为30.07GB、最小值为3.76GB。

ARC为MRU和MFU缓存平均分配了内存。

zfs-stats -E 给出的ARC效率报告比一般报告更有趣。下面是来自不同服务器的输出的最有趣的片段。

ZFS将大量内存专用于文件系统缓存。本报告的顶部向我们展示了我们从中获得的好处。高速缓存命中率表示从ARC而不是通过发送到磁盘来满足磁盘读取请求的百分比。在这种情况下,该机器上97.76%的所有读取请求都是在内存不足的情况下提供的。百分比后的数字是请求的原始数量。该主机为ARC中的76.65m(百万)个磁盘请求提供服务。

接下来,zfs-stats 显示缓存文件来自哪个缓存。

MRU缓存类似于传统的缓冲区缓存,为ARC提供的所有文件的3.35%提供服务。96.65%的文件来自MFU缓存。在没有MFU缓存的情况下,这些队列之间肯定存在一些重叠,一些经常访问的文件将出现在MRU缓存中。但它很好地说明了ARC为什么使用MFU缓存。

重影(ghosts)保存最近缓存的数据列表,但由于内存压力或其他限制而被丢弃。添加更多内存和增加ARC大小是否会提高缓存命中率?当重影列表命中率为0.04%和0.08%时,添加更多内存并不会真正改善缓存。此主机的ARC只有36%已满,因此不会收回项目。这些微小的百分比可能是数万个请求,但与它所服务的数百万个请求相比,这几乎算不上什么。额外的内存可能会改善其他进程,但不会改善ARC。

接下来,我们看到从ARC中提取的数据类型。

数据是文件的内容,而元数据是关于文件的一切。我们在第8章中讨论了预取(prefetching),但无论预取是什么,它在这里显然不起作用。

另一方面,我们可以看到哪些类型的数据没有被缓存。

应在ARC之外为多少系统请求提供服务?这完全取决于工作量。反复服务相同数据的web服务器可能会期望高缓存命中率。在客户端访问许多不同文件的服务器上,预期缓存命中率较低。如果您的池在数百万个文件中具有TB级的数据,但客户端从未两次访问同一数据文件,则在内存中缓存文件不会提高性能。

修改 ARC

ZFS ARC在绝大多数情况下自行管理。在ARC不能自动调谐自身的大多数情况下,性能问题最好通过添加硬件来解决。然而,有时调整ZFS的内存或性能可以为您赢得时间,直到您可以接收和安装新硬件。在极少数情况下,调整ARC是特定应用的适当响应。

您可以通过设置ARC能使用多少内存的上限和下限,以及控制ARC缓存数据的内容、时间和原因来调整ARC。

限制 ARC 大小

默认的FreeBSD安装为内核和操作程序预留了1GB的RAM,如果系统性能需要,则允许ZFS吸收ARC中的其余内存。您可以通过为ARC保留最小内存量和/或设置ARC可以占用的内存量的硬限制来更改这一点。

ARC设置均以字节为单位。今天,我们以GB为单位管理内存。要设置ZFS的值,请将所需的千兆字节数乘以1024。

ARC在请求时很容易放弃内存,但释放内存不会立即发生。毫无疑问,从ARC释放内存并将其分配给另一个进程所需的时间比将空闲内存分配给同一个进程要长。在具有非常大ARC的主机上,从缓存转储千兆字节的对象可能需要一秒钟的时间。

您可以决定限制ARC可以使用的内存量,为应用程序释放系统内存。使用引导时间可调的 vfs.zfs.arc_max 来设置此项。默认情况下,FreeBSD将其设置为总内存减去1 GB。下面例子中,我们在 /boot/loader.conf 中设置了20 GB的上限。

最大ARC大小不是硬限制,而是高水位线(high-water mark)。当ARC达到此大小时,ZFS开始匆忙减少缓存大小。最不重要的项被添加到重影队列(ghost queues)并转储。如果正在监视ARC大小,则当系统遇到内存压力时,您可能会看到内存使用量在 vfs.zfs.arc_max 周围波动。

应用程序也可能使用ARC的慷慨来对付它,并将其挤出。ARC的默认最小大小是最大大小的八分之一。(严格地说,最小ARC大小是ARC中可用于元数据的最大内存量的一半,即最大ARC大小的四分之一。)使用引导时间可调 vfs.zfs.arc_min 来设置最小ARC尺寸。与最大大小一样,最小大小以字节表示。在这里,我在 /boot/loader.conf 中将最小ARC大小设置为4 GB。

Lucas通常只在厌倦向非技术经理解释ARC的工作方式时设置ARC大小的上限和下限。”是的,PostgreSQL可以使用大量内存。ARC使用内存。但ARC仅缓存PostgreSQL调用的内容,PostgreSQL必须启动并运行才能做到这一点,因此这不是问题。“

FreeBSD 10.2和更高版本可以使用sysctl vfs.zfs.arc_free_target 指定ARC应尝试留出多少内存供其他进程使用。该值与本节中的其他值不同,因为它是以页面而不是字节来指定的。页面是4096字节的内存,因此2 GB的值将表示为524288(2*10243/4096)。当可用内存量降至该值以下时,内核内存收获器将运行。收割器执行两个功能:它调整ARC的大小以确保有足够的可用内存,并对 KMEM Arena 进行碎片整理。当文件移入移出ARC时,ZFS一直在快速分配和释放内存位,但它在内核内存的不同段上散乱了位。在释放竞技场中的所有分配之前,该内存不会返回 free 状态。这表现为 wired 内存量显著高于ARC的大小加上预期的其他有线页面(如网络堆栈)。与前面的可调参数不同, vfs.zfs.arc_free_target 可以在正在运行的系统上进行调整,并立即生效。

元数据和 ARC

文件系统元数据包括有关文件的所有内容,除了文件本身,还包括目录、权限、所有权、大小、属性等。ARC缓存所有这些信息,就像缓存文件内容一样。毕竟,访问文件的内容需要访问文件的元数据。

默认情况下,ARC最多使用其最大大小的四分之一来缓存此元数据。虽然这几乎总是足够的,但如果文件系统有一大堆小文件,则可能需要扩展此限制。引导时间可调的 vfs.zfs.arc_meta_limit 允许您为元数据配置特定的限制,该限制可以高于或低于默认值。在这里,我们在 /boot/loader.conf 中将ARC的元数据缓存硬编码为8 GB。

如果 zfs-stats -E 显示您从ARC中提取的数据比元数据多得多,那么您可以考虑增加元数据限制,并查看性能是否提高。请记住,默认情况下,ARC的最小大小是可用于元数据的量的一半。此外,缓存的元数据不能使用比整个ARC更多的空间。

数据集和 ARC

一些数据具有常规访问模式,使得ARC在第二次访问任何文件时不相关,它早就从MRU和MFU列表中过期了。这通常仅在数据集包含数百万个文件并且您可以轻松预测其使用情况时发生。告诉ARC不要缓存这些文件可以释放内存来缓存可能会受益的文件。

ZFS属性 primarycache 定义数据集信息的哪些部分应进入ARC。

例如,Lucas的一个服务器有一个TB级的数据集,其中包含在过去15年中创建的无数文件。在很少访问这些文件的情况下,会按顺序搜索它们。服务器没有足够的内存来有效地缓存所有这些文件的内容。告诉ARC在该数据集上缓存元数据意味着 ls(1) 等仍然可以快速工作,但我们不会无谓地扰乱这台机器的ARC。

在对 primarycache 属性的更改生效之前,必须卸载并重新装载数据集。

ARC现在可以免费进行有用的工作,例如缓存通过分析这些记录创建的临时文件。

卸载数据集会从ARC和L2ARC中删除有关该数据集的所有缓存信息。

Level 2 ARC(二级ARC)

ARC不断修剪自己,以保持在允许的大小范围内。长时间未被引用的文件将从MRU列表中删除。通常,从ARC中删除的项目会蒸发——当它们在幽灵列表(ghost lists)中被提及时,如果它们再次出现,MFU队列可以识别它们,系统依赖于文件的磁盘副本。

2级ARC(或称 L2ARC)是一个辅助读缓存。L2ARC捕获从ARC脱落的项目。通过使用小型、快速、高耐久性的磁盘缓存ARC数据,您可以同时减少系统主存储器上的读取负载并提高读取性能。zpool(8) 命令将L2ARC称为 cache device

当L2ARC写入磁盘时,其中的数据无法在重新启动后继续存在。当一切都安全地存在时,该数据的索引将被销毁。即使这些索引可用,在重新启动系统之前,池也可以在其他计算机上进行修改。ZFS无法信任缓存设备上的信息。

截至2016年初,持久L2ARC的实现接近完成。有了持久L2ARC,系统将重新加载以前的L2ARC,并将所有内容加载回内存。虽然此功能可能永远不会广泛分发,但大量L2ARC用户可能会在将来检查它。

当多个用户、虚拟机或应用程序访问单个数据集时,使用L2ARC是有意义的。如果工作集大于您可以负担的RAM数量,则第二个选择是基于SSD或NVMe设备的L2ARC。对于大多数应用程序,如典型的家庭或企业NAS,L2ARC不会提高性能L2ARC甚至可以通过内存消耗来损害性能

L2ARC 内存使用

虽然L2ARC包含一大堆缓存数据和元数据,但这些数据的索引驻留在ARC中。一般来说,每GB的L2ARC需要大约25MB的ARC。这取决于磁盘的扇区大小、记录大小属性和其他数据集特征,这使得实际大小难以计算。一个合理的预期是,1TB的L2ARC将消耗大约25GB的ARC。

大多数L2ARC不到1TB——至少还没到。具有足够高耐久性以使其适合读取缓存的SSD仍然非常昂贵,以至于我们大多数人都没有它们。那些计划使用40个以上驱动器的大规模存储阵列的人应该记住这一点。

L2ARC 缓存

L2ARC只能缓存从ARC脱落的数据。从未在ARC中出现的数据也不会出现在L2ARC中。

假设你通过将 primarycache 属性设置为 none ,完全禁用了特定池上所有数据集的ARC缓存,向此池中添加L2ARC不会提高ZFS性能,因为没有缓存数据会降到L2ARC中。

您可能认为有一个ARC包含元数据的数据集,而L2ARC缓存实际的文件数据是有意义的。Lucas上一节中的多TB cdr/cdr 数据集可能是这方面的一个很好的候选者。一旦他将 primarycache 设置为 metadata ,看起来肯定会发生这种情况。

问题是ARC只缓存元数据,因此它只能向L2ARC推送元数据。L2ARC只能包含ARC中的内容或其子集。

默认情况下,ARC会缓存系统访问的所有内容,因此L2ARC也会这样做。

可以使用 secondarycache 属性控制每个数据集如何使用L2ARC。类似 primarycache 属性, secondarycache 可以设置为 allmetadatanone 。默认为 all ,意味着对于主ARC来说几乎足够重要的数据会被推送到L2ARC上。

流播文件

读取文件所需的大部分时间都花在将磁头移动到盘片上方的位置上。一旦定位,磁头会很快读取数据。这被称为 streaming ——流播。虽然在内存外提供大文件比从磁盘读取快,但在大多数系统上,主池的多个磁盘比L2ARC的一两个磁盘快。在这种情况下,使用L2ARC缓存流文件没有意义,因此默认情况下是禁用的。

如果你有一个比主池快的L2ARC,你可能想启用大文件缓存。在 /boot/loader.conf 中设置 vsf.zfs.l2arc_noprefetch 的值为 0 以启用缓存(默认值为 1 ,禁用缓存流文件):

此可调项仅在导入池时生效。FreeBSD在查看 /etc/sysctl.conf 之前导入池,因此必须在引导加载程序——/boot/loader.conf 中设置。

L2ARC 写入速度

SSD不如旋转磁盘那么健壮。即使您与非常熟悉ZFS并确切知道用于L2ARC的最佳磁盘的专业供应商(如iX Systems)联系,您也只能在SSD死亡之前敲击它。虽然ZFS优雅地管理濒死或死亡(dying or dead)的L2ARC,但持续磁盘死亡代价高昂、耗时,并且让系统管理员感到厌烦。ZFS在L2ARC上实现了几个写入限制,以延长磁盘寿命。

与主ARC一样,L2ARC在其配置中使用字节。大多数L2ARC设置以兆字节为单位最有意义。将所需值乘以10242

在正常操作期间,ZFS每秒仅向每个L2ARC设备写入8 MB。这避免了SSD设备的磨损,也有助于避免缓存抖动。(cache thrashing——缓存抖动是将大量数据写入高速缓存,而这些数据在使用之前只会被更新的数据覆盖。)如果需要系统的L2ARC来处理更多数据,可以使用sysctl vfs.zfs.L2ARC_write_max 来增强这一点。不要将其调高到使读取变慢。

系统首次引导时,L2ARC为空。空的L2ARC没有多大用处。ZFS在系统引导后执行Turbo预热阶段(Turbo Warmup Phase),其中它将额外数据写入L2ARC,超过 vfs.ZFS.L2ARC_write_max 设置的限制。Turbo预热阶段将继续,直到ARC从L2ARC中删除第一个项目。这所需的时间长度完全取决于系统。默认情况下,ZFS可以在Turbo预热阶段向每个L2ARC设备额外写入8 MB。sysctl vfs.zfs.l2arc_write_boost 控制分配的额外带宽。

您可以随时更改这些系统。在这里,我们将两者都设置为16MB。

当然,软件设置不会让您超过硬件的限制。

SSD不像以前那么脆弱了。现代数据中心级SSD(如200 GB Intel DC S3700)的耐久性评级为“5年内每天10次驱动器写入”。这意味着每天大约2000 GB,或23 MB/秒。您可以不断地向该驱动器写入23MB/s,根据英特尔的说法,它将持续五年。在高性能服务器上,将节流系统(throttle sysctls)调到这些值,并添加注释以在58个月内订购新的缓存设备是有意义的。由于您的主机可能不会一直全速写入L2ARC,因此将这些参数调高可能是有意义的。

ZFS 意图日志——ZIL

缓存不仅仅用于读取数据。ZFS也通过ZFS意向日志(ZFS Intent Log,ZIL)使用缓存进行写入。ZFS将写入转储到ZIL,然后处理这些写入,以将其正确添加到ZFS。每个池都有自己的ZIL。在正常使用中,ZFS在每个提供程序上为ZIL使用一块空间。如果需要,可以添加外部设备用作ZIL。严格地说,ZIL并不完全是一个写缓存。但这是一种恶作剧,所以我们将在本章中讨论它。

然而,ZIL并不像大多数人认为的那样工作。要了解池何时需要单独的日志记录设备,何时不需要,您必须了解ZFS如何写入数据。

同步和异步事务

ZFS是关于到达永久存储的数据的完整性的。磁盘上的数据应始终保持一致。系统可能会丢失程序和磁盘之间的数据,但没有任何文件系统可以保护仅驻留在RAM中的动态数据。

为了确保磁盘上数据的完整性,ZFS组在事务组(transaction,或称 txgs)中写入请求。事务组是一组数据和相关的文件系统元数据。当您要求系统写入磁盘时,ZFS会在事务组中收集这些写入。一个事务组可以包括来自许多不相关进程的写入。一旦组具有足够的数据或计时器过期,该事务组就会写入磁盘。该计时器可能长达30秒,也可能短至5秒,具体取决于您正在运行的FreeBSD版本。

事务组是文件系统的待办事项列表。就像你的待办事项清单一样,如果发生了可怕的事情,清单就会被扔给狼。数据在完全写入磁盘之前容易发生系统故障。如果在事务组写入磁盘之前系统崩溃或死亡,则该数据将丢失。减少事务组超时可能会减少数据丢失量,但它也会严重影响性能

作为系统管理员,管理数据丢失风险是您的工作。让我们来看看如何将数据写入磁盘。

程序将一块数据交给内核,并说,“请将此写入磁盘。”直到内核确认收到数据,程序才会继续。一旦内核说“我有数据”,程序继续。等待此响应的程序被称为在I/O上阻塞(blocking on I/O)。

重要的问题是:内核何时确认收到数据?何时将数据添加到事务组,或何时将其写入磁盘?

在正常操作中,当数据作为挂起事务组的一部分在内存中时,内核确认(acknowledges)数据。数据不在磁盘上,内核只是声称对数据负责。如果该系统是一家餐厅,晚餐现在将在服务员手中,在去送给顾客的路上,但服务员仍然可能绊倒。异步(asynchronous——async)操作的变体在现代文件系统中很常见,例如Linux的extfs和BSD UFS的各种版本。

文件系统也可以在同步(synchronous——sync)模式下工作,其中内核仅在位(bits)实际写入物理存储介质时才确认数据。同步挂载非常安全,但速度也非常慢。写入数据的程序将阻塞等待物理硬件响应内核的写入请求。某些程序(如数据库服务器)通过使用 fsync(2) 系统调用请求特定文件的同步确认。系统管理员可以同步挂载数据集,以便系统仅在写入完成时确认数据,或者可以使用 fsync(8) 程序告诉系统立即将所有内容刷新到磁盘。

ZFS 意图日志

当ZFS以同步模式写入文件时,它不会立即将事务组推送到磁盘,相反,这些数据会被丢到ZIL上。它们没有整齐地排列成ZFS数据集块;相反,它们只是磁盘上的一堆块。当事务组被写入磁盘时,ZIL上的块被写入到它们的正确位置。

池导入过程检查ZIL中尚未到达其最终位置的数据。如果系统在其导入的池中发现正在运行的块,则完成这些事务。

池通常使用每个存储提供者上的一小块空间作为ZIL。是的,这意味着每次同步写入都会被写入物理存储两次。但是该池只使用ZIL来同步写入数据。正常的异步写入存储在RAM中,并作为常规事务组的一部分提交。

有时,你可以通过将ZIL放在一个专用的快速设备上来提高性能,该设备称为单独意图日志(Separate Intent LOG——SLOG)。

单独意图日志

可以使用单独意图日志( Separate Intent Log,SLOG)将ZIL从池中分离出来。通过将ZIL移动到单独的专用硬件,可以避免将相同的数据写入存储提供程序两次。如果SLOG硬件比池更快,则内核可以更快地确认数据,从而提高请求应用程序的性能。

尽管有常见的用法,SLOG与ZIL不是一回事。SLOG是硬件。ZIL位于SLOG或存储提供程序上。您可以通过窗口启动SLOG,但您只能对ZIL发誓。

最快、最可靠、最昂贵的SLOG是NVRAM芯片。高耐久性SSD是SLOG最常见的选择。您甚至可以使用非常快的SAS驱动器,但它们是最不可靠的。其中每一个都需要一个专用电源,如电池或超级电容器,以便在系统电源故障时完成写入。

SLOG不需要很大。sysctl vfs.zfs.dirty_data_max 提供最大可能的飞行中数据量。FreeBSD 10的ZFS默认使用大小等于系统RAM十分之一的ZIL。您可以使用单个硬件来支持多个池的SLOG提供程序,但这也会在这些池之间拆分该设备的I/O。使用SLOG的一个原因是为了处理I/O短缺(shortages)。

并非所有SSD或NVRAMs的创建都相同。许多销售为“高持久性”的设备不够健壮,甚至不能处理中型池的所有写入。对于数据完整性至关重要的应用程序,作者强烈建议您咨询专门从事ZFS的硬件供应商,如iX Systems(www.ixsystems.com)。正确选择的SLOG可以极大地加速您的程序,而错误的选择可能会损坏您的池。

每个数据集ZIL调优

你可以控制数据集如何(或是否)使用具有 sync 属性的ZIL。就像挂载传统的文件系统同步或异步一样,sync 属性决定了数据集是否接受 fsync(2) 请求。

在几乎所有情况下,保持 syncstandard 。可能有一两个数据集需要将 sync 设置为 always

通过堆栈进行同步写入

ZFS最终成为许多不同应用程序(如网络文件系统(NFS)和iSCSI)的数据存储后端。您可以将zvol用于虚拟化系统的驱动器。所有这些不同的层都独立运行。虽然它们可以通过公共系统调用和API相互通信,但它们并不相互控制。应用程序堆栈的每一层都可以(并且通常是这样)位于其他层。这一点最明显、最危险的莫过于 fsync(2) 系统调用。

假设您有一个运行iSCSI驱动器的虚拟机,由服务器上的zvol提供支持。虚拟机的操作系统请求同步磁盘写入。iSCSI堆栈接受该请求并将其传递给ZFS。如果您在zvol ZFS窃笑器上将 sync 设置为 disabled ,则会说“同步?当然!你知道了,伙计”,然后等待做任何事情,直到下一次txg。

您可以将 sync 设置为始终在zvol上,以数据完整性的名义接受性能命中。但是,如果iSCSI堆栈禁用同步写入,您将遭受这种打击,而没有任何好处。复杂应用程序堆栈的任何层都可能禁用同步写入。

如果数据完整性很重要,请验证同步写入是否在整个应用程序堆栈中工作。

zpool.cache

现在,让我们讨论一个缓存,您将听到这个缓存,但它不会影响日常的系统管理:文件 /boot/zfs/zpool.cache

zpool.cache 文件包含系统上当前活动的池及其提供程序的描述。引导ZFS系统时,内核检查根池上的 zpool.cache 文件,以发现应该导入的系统池。

ZFS的 zdb(8) 使用缓存文件中的信息进行调试。不能在没有缓存的池上使用调试器。

可以使用 cachefile 属性控制缓存文件的位置。在这里,我们更改池 work 的缓存文件。

尽管有许多挥之不去、过时的文档,但几乎没有理由在现代版本的ZFS或FreeBSD上更改缓存文件位置。

现在您已经了解了缓存,我们可以谈谈性能。