{"id":83582,"date":"2020-06-01T19:42:21","date_gmt":"2020-06-01T17:42:21","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/osnovy-zfs-sistema-hraneniya-i-proizvoditelnost"},"modified":"2020-06-01T19:42:21","modified_gmt":"2020-06-01T17:42:21","slug":"osnovy-zfs-sistema-hraneniya-i-proizvoditelnost","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/osnovy-zfs-sistema-hraneniya-i-proizvoditelnost","title":{"rendered":"Basics of ZFS: storage system and performance","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/70d75786f36a92a0407107fb79bee721.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nThis spring, we have already discussed some introductory topics, such as <noindex><a rel=\"nofollow\" href=\"https:\/\/arstechnica.com\/gadgets\/2020\/02\/how-fast-are-your-disks-find-out-the-open-source-way-with-fio\/\">how to check your disk speed<\/a><\/noindex> and <noindex><a rel=\"nofollow\" href=\"https:\/\/arstechnica.com\/information-technology\/2020\/04\/understanding-raid-how-performance-scales-from-one-disk-to-eight\/\">what RAID is<\/a><\/noindex>. In the second part, we even promised to continue exploring the performance of various multi-disk topologies in ZFS. This is a next-generation file system that is being implemented everywhere: from <noindex><a rel=\"nofollow\" href=\"https:\/\/arstechnica.com\/gadgets\/2016\/06\/a-zfs-developers-analysis-of-the-good-and-bad-in-apples-new-apfs-file-system\/\">Apple<\/a><\/noindex> up to <noindex><a rel=\"nofollow\" href=\"https:\/\/arstechnica.com\/information-technology\/2020\/05\/ubuntu-20-04-welcome-to-the-future-linux-lts-disciples\/\">Ubuntu<\/a><\/noindex>.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nWell, today is the perfect day to get to know ZFS, curious readers. Just know that according to OpenZFS developer Matt Ahrens, \u201cit\u2019s really complicated.\u201d<\/p>\n<p>But before we get to the numbers \u2014 and I promise there will be, covering all options of the eight-disk configuration of ZFS \u2014 we need to talk about <i>as<\/i> how ZFS actually stores data on disk.<\/p>\n<h1>Zpool, vdev, and device<\/h1>\n<p>\n<img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/d881cb44e935480a6f2c30795d6afaf1.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>This full pool diagram includes three auxiliary vdevs, one of each class, and four for RAIDz2.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/fa52fcf700cc72105a90e4ddc4724d9a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Usually, there\u2019s no reason to create a pool from mismatched types and sizes of vdev \u2014 but if you want, nothing prevents you from doing so<\/i><\/p>\n<p>To truly understand the ZFS file system, you need to take a close look at its actual structure. First, ZFS combines traditional levels of volume management and file system. Second, it uses a copy-on-write transactional mechanism. These features mean that the system is structurally very different from regular file systems and RAID arrays. The first set of fundamental building blocks for understanding is: storage pool (zpool), virtual device (vdev), and physical device (device).<\/p>\n<h3>zpool<\/h3>\n<p>\nThe storage pool zpool is the topmost structure of ZFS. Each pool contains one or more virtual devices. In turn, each of these contains one or more physical devices (device). Virtual pools are standalone blocks. One physical computer can contain two or more separate pools, but each one is completely independent of the others. Pools cannot share virtual devices.<\/p>\n<p>ZFS redundancy exists at the level of virtual devices, not at the level of pools. At the pool level, there is absolutely no redundancy \u2014 if any vdev or special vdev storage is lost, the entire pool is lost along with it.<\/p>\n<p>Modern storage pools can withstand the loss of cache or log from a virtual device\u2014though they may lose a small amount of dirty data if the vdev log is lost during a power outage or system failure.<\/p>\n<p>There is a common misconception that ZFS data stripes are written across the entire pool. This is incorrect. Zpool is not simply a fun RAID0; it is rather complex. <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Non-RAID_drive_architectures#JBOD\">JBOD<\/a><\/noindex> with a complex variable distribution mechanism.<\/p>\n<p>For the most part, writes are distributed across available virtual devices according to the free space available, so theoretically, they will all fill up simultaneously. In later versions of ZFS, the current utilization of the vdev is taken into account\u2014if one virtual device is significantly busier than another (for example, due to a heavy read load), it will be temporarily skipped for writes despite having the highest free space ratio.<\/p>\n<p>The utilization determination mechanism built into modern ZFS write distribution methods can reduce latency and increase throughput during periods of unusually high load\u2014but this is not <i>a blank check<\/i> for unintentional mixing of slow HDDs and fast SSDs in one pool. Such an imbalanced pool will still operate at the speed of the slowest device, as if it were entirely made up of those devices.<\/p>\n<h3>vdev<\/h3>\n<p>\nEach storage pool consists of one or more virtual devices (vdev). Each vdev, in turn, contains one or more physical devices. Most virtual devices are used for simple data storage, but there are several auxiliary classes of vdev, including CACHE, LOG, and SPECIAL. Each of these types of vdev can have one of five topologies: single-device, RAIDz1, RAIDz2, RAIDz3, or mirror.<\/p>\n<p>RAIDz1, RAIDz2, and RAIDz3 are special types of what old-timers might call double (diagonal) parity RAID. The 1, 2, and 3 refer to how many parity blocks are allocated for each data stripe. Instead of using separate disks for parity, RAIDz virtual devices distribute this parity semi-evenly across disks. A RAIDz array can lose as many disks as it has parity blocks; if it loses one more, it will fail and take the storage pool with it.<\/p>\n<p>In mirror virtual devices (mirror vdev), each block is stored on every device in the vdev. While the most common configuration is a two-wide mirror, any arbitrary number of devices can be included in a mirror\u2014triple mirrors are often used in larger installations to enhance read performance and fault tolerance. A vdev mirror can survive any failure as long as at least one device in the vdev is still operational.<\/p>\n<p>Single vdevs are inherently dangerous. Such a virtual device will not survive any failure\u2014if used as storage or a special vdev, its failure will result in the destruction of the entire pool. Exercise extreme caution here.<\/p>\n<p>CACHE, LOG, and SPECIAL virtual devices can be created using any of the aforementioned topologies\u2014but remember that losing a SPECIAL virtual device means losing the pool, so redundant topology is highly recommended.<\/p>\n<h3>device<\/h3>\n<p>\nProbably the easiest term to understand in ZFS\u2014it's literally a block device of random access. Remember, virtual devices are made up of individual devices, and a pool is made up of virtual devices.<\/p>\n<p>Disks\u2014magnetic or solid-state\u2014are the most common block devices used as building blocks for vdev. However, any device with a descriptor in \/dev will work\u2014so entire hardware RAID arrays can be used as individual devices.<\/p>\n<p>A simple raw file is one of the most important alternative block devices from which a vdev can be constructed. Test pools from <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Sparse_file\">sparse files<\/a><\/noindex>\u00a0are a very convenient way to test pool commands and see how much space is available in the pool or virtual device of this topology.<\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/d9bea0e4a6842742a7dbac2f9b1ba394.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>You can create a test pool from sparse files in just a few seconds\u2014 but don't forget to delete the entire pool and its components afterward.<\/i> <\/p>\n<p>Let's say you want to set up a server with eight disks and plan to use 10 TB (~9300 GiB) disks\u2014 but you're not sure which topology best meets your needs. In the example above, we construct a test pool from sparse files in a matter of seconds\u2014 and now we know that a RAIDz2 vdev with eight 10 TB disks provides 50 TiB of usable capacity.<\/p>\n<p>Another special class of devices is SPARE. Hot-swappable devices, unlike regular devices, belong to the entire pool rather than a single virtual device. If any vdev in the pool fails and a spare device is connected and available, it will automatically attach to the affected vdev.<\/p>\n<p>Once connected to the affected vdev, the spare device begins receiving copies or reconstructions of the data that should be on the missing device. In traditional RAID, this is called rebuilding, while in ZFS, it is termed \"resilvering.\"<\/p>\n<p>It is important to note that spare devices do not permanently replace failed devices. They are a temporary substitute to reduce the time during which vdev is degraded. After the administrator replaces the failed vdev device, the resilvering occurs on that permanent device, and the SPARE detaches from vdev and returns to being a spare for the entire pool.<\/p>\n<h1>Datasets, blocks, and sectors<\/h1>\n<p>\nThe next set of building blocks to understand in our journey through ZFS relates not so much to hardware as to how the data itself is organized and stored. We are skipping several levels\u2014 such as metaslab\u2014 to avoid overwhelming details while maintaining an understanding of the overall structure.<\/p>\n<h3>Dataset<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/6a4dc218bd1c57989739d5072f13804c.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>When we first create a dataset, it shows all the available space in the pool. We then set a quota\u2014 and change the mount point. Magic!<\/i> <\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/aeb6763d6e78e3cc7ee8b1d39ee98b46.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Zvol is essentially just a dataset devoid of its filesystem layer, which we replace here with a perfectly normal ext4 filesystem.<\/i> <\/p>\n<p>A ZFS dataset is roughly analogous to a standard mounted filesystem. Like a regular filesystem, at first glance, it seems like \"just another folder.\" However, much like standard mounted filesystems, each ZFS dataset has its own set of base properties.<\/p>\n<p>First of all, a dataset can have an assigned quota. If you set <code>zfs set quota=100G poolname\/datasetname<\/code>, then you will not be able to write to the mounted folder <code>\/poolname\/datasetname<\/code> more than 100 GiB.<\/p>\n<p>Did you notice the presence\u2014and absence\u2014of slashes at the beginning of each line? Each dataset has its place in both the ZFS hierarchy and the system mounting hierarchy. In the ZFS hierarchy, there is no leading slash\u2014you start with the pool name and then the path from one dataset to the next. For example, <code>pool\/parent\/child<\/code> for a dataset named <code>child<\/code> under the parent dataset <code>parent<\/code> in a creatively named pool. <code>pool<\/code>.<\/p>\n<p>By default, the mount point of a dataset will be equivalent to its name in the ZFS hierarchy, with a slash at the beginning\u2014the pool named <code>pool<\/code> will be mounted as <code>\/pool<\/code>, the dataset <code>parent<\/code> is mounted at <code>\/pool\/parent<\/code>, and the child dataset <code>child<\/code> is mounted at <code>\/pool\/parent\/child<\/code>. However, the system mount point of a dataset can be changed.<\/p>\n<p>If we specify <code>zfs set mountpoint=\/lol pool\/parent\/child<\/code>, then the dataset <code>pool\/parent\/child<\/code> will be mounted in the system as <code>\/lol<\/code>.<\/p>\n<p>In addition to datasets, we must mention volumes (zvols). A volume is somewhat analogous to a dataset, except that it actually doesn\u2019t have a filesystem\u2014it\u2019s just a block device. For example, you can create <code>zvol<\/code> named <code>mypool\/myzvol<\/code>, then format it with the ext4 filesystem, and then mount this filesystem\u2014now you have an ext4 filesystem, but with all the security features of ZFS! This may seem silly on a single computer, but it makes much more sense as a backend when exporting iSCSI devices.<\/p>\n<h3>Units<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/ce96416cd2fa08ff615f13ccec72e838.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>A file is represented by one or more blocks. Each block is stored on one virtual device. The block size is usually equal to the parameter <b>recordsize<\/b>, but can be reduced to <b>2^ashift<\/b>, if it contains metadata or a small file.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/f31c25e34af12a9a96b60a46c2924053.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>We really <b>really<\/b> aren't joking about the enormous performance penalty if you set ashift too small.<\/i><\/p>\n<p>In a ZFS pool, all data, including metadata, is stored in blocks. The maximum block size for each dataset is defined by the property <code>recordsize<\/code> (record size). The record size can change, but this does not affect the size or location of any blocks that have already been written to the dataset\u2014it only applies to new blocks as they are written.<\/p>\n<p>If not specified otherwise, the default record size is 128 KiB. This is somewhat of a compromise, where the performance will not be ideal, but it won't be terrible in most cases. <code>Recordsize<\/code> can be set to any value from 4K to 1M (with additional settings <code>recordsize<\/code> it can be set even larger, but this is rarely a good idea).<\/p>\n<p>Any block refers to the data of only one file\u2014you cannot squeeze two different files into one block. Each file consists of one or more blocks, depending on its size. If the file size is smaller than the record size, it will be stored in a smaller block\u2014 for example, a block with a 2 KiB file will occupy only one 4 KiB sector on the disk.<\/p>\n<p>If the file is large enough and requires multiple blocks, then all records with this file will have a size <code>recordsize<\/code>\u00a0\u2014 including the last record, the main part of which may turn out to be <noindex><a rel=\"nofollow\" href=\"https:\/\/whatis.techtarget.com\/definition\/slack-space-file-slack-space\">unused space.<\/a><\/noindex>.<\/p>\n<p>Zvols do not have the property <code>recordsize<\/code>\u00a0\u2014 instead, they have an equivalent property <code>volblocksize.<\/code>.<\/p>\n<h3>Sectors<\/h3>\n<p>\nThe last, most basic building block is the sector. This is the smallest physical unit that can be written or read from the underlying device. For several decades, sectors of 512 bytes were used in most disks. Recently, most disks have been configured for 4 KiB sectors, and in some\u2014especially SSDs\u20148 KiB sectors or even larger.<\/p>\n<p>In the ZFS system, there is a property that allows you to manually set the sector size. This property <code>ashift<\/code>. It is somewhat confusing that ashift is a power of two. For example, <code>ashift=9<\/code> means a sector size of 2^9, or 512 bytes.<\/p>\n<p>ZFS queries the operating system for detailed information about each block device when it is added to a new vdev, and theoretically automatically sets ashift correctly based on this information. Unfortunately, many disks lie about their sector size to maintain compatibility with Windows XP (which was unable to understand disks with other sector sizes).<\/p>\n<p>This means that it is highly recommended for ZFS administrators to know the actual sector size of their devices and set it manually. <code>ashift<\/code>. If ashift is set too low, the number of read\/write operations increases astronomically. For example, writing 512-byte 'sectors' to an actual 4 KiB sector requires writing the first 'sector', then reading the 4 KiB sector, modifying it with the second 512-byte 'sector', writing it back to a new 4 KiB sector, and so on for each write.<\/p>\n<p>In the real world, such a penalty affects Samsung EVO solid-state drives, for which it should be <code>ashift=13<\/code>, but these SSDs lie about their sector size, which is why it is set by default to <code>ashift=9<\/code>. If an experienced system administrator does not change this parameter, the SSD operates <i>slower.<\/i> like a regular magnetic HDD.<\/p>\n<p>In comparison, there is practically no penalty for setting too large a size. <code>ashift<\/code> There is no real performance degradation, and the increase in unused space is infinitesimal (or zero when compression is enabled). Therefore, we strongly recommend even for those disks that actually use 512-byte sectors to set <code>ashift=12<\/code> or even <code>ashift=13<\/code>, to confidently look to the future.<\/p>\n<p>window.name <code>ashift<\/code> This is set for each virtual device vdev, and <i>not for the pool<\/i>, as many mistakenly believe \u2014 and does not change after it is set. If you accidentally misconfigured <code>ashift<\/code> when adding a new vdev to the pool, you have irrevocably polluted that pool with a low-performance device and generally there is no other option but to destroy the pool and start over. Even removing the vdev won't save you from the misconfiguration. <code>ashift<\/code>!<\/p>\n<h3>The copy-on-write mechanism<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/eb222dbcc3de428ff2b1c2c72b145db0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>If a regular file system needs to rewrite data, it modifies each block where it is located.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/ba2474808b32667902966e4c9e69081a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>The copy-on-write file system writes a new version of the block and then unlocks the old version.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/3b00dad44eb588ed793d2d5df7852892.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>In abstract terms, ignoring the actual physical location of the blocks, our 'data comet' simplifies to a 'data worm' that moves left to right across the map of available space.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/8c2c38dbc8a5e633c466d5c7f230951f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Now we can get a good understanding of how copy-on-write snapshots work \u2014 each block can belong to multiple snapshots and will remain until all associated snapshots are destroyed.<\/i><\/p>\n<p>The copy-on-write mechanism (CoW) is the fundamental basis of what makes ZFS such an amazing system. The core concept is simple \u2014 if you ask a traditional file system to change a file, it will do exactly what you asked. If you ask a copy-on-write file system to do the same, it will say 'sure' \u2014 but it will lie to you.<\/p>\n<p>Instead, the copy-on-write file system writes a new version of the modified block and then updates the file's metadata to break the link with the old block and associate it with the new block you just wrote.<\/p>\n<p>The disconnection of the old block and linking of the new one occurs in a single operation, so it cannot be interrupted \u2014 if you lose power after it happens, you have a new version of the file, and if you lose power before, you have the old version. In either case, no conflicts will arise in the file system.<\/p>\n<p>Copy-on-write in ZFS occurs not only at the file system level but also at the disk management level. This means that ZFS is not subject to a write hole (<noindex><a rel=\"nofollow\" href=\"http:\/\/www.raid-recovery-guide.com\/raid5-write-hole.aspx\">a RAID hole<\/a><\/noindex>) \u2014 a phenomenon where the stripe was only partially written before the system failure, resulting in data corruption after reboot. Here, the stripe is written atomically, the vdev is always consistent, and <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Bob%27s_your_uncle\">Bob's your uncle.<\/a><\/noindex>.<\/p>\n<h3>ZIL: ZFS Intent Log<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/8d08b7bce60a1e3698fd0ec02494e6fe.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>The ZFS system handles synchronous writes specially \u2014 it temporarily but immediately saves them in the ZIL, before later committing them permanently along with asynchronous writes.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/2119ef409a7d8c9599ee63292452d80d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Usually, data written to the ZIL is never read again. But it is possible after a system failure.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/88a62163b0fb9f14a41102821dfabb5f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>SLOG, or secondary LOG device, is simply a special \u2014 and ideally very fast \u2014 vdev where the ZIL can be stored separately from the main storage.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/819f7c21714adafe226028e95990f1df.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>After a failure, all dirty data in the ZIL is replayed \u2014 in this case, the ZIL is on the SLOG, so it is replayed from there.<\/i><\/p>\n<p>There are two main categories of write operations \u2014 synchronous (sync) and asynchronous (async). For most workloads, the overwhelming majority of write operations are asynchronous \u2014 the file system allows them to be aggregated and issued in batches, reducing fragmentation and significantly increasing throughput.<\/p>\n<p>Synchronous writes, however, are a completely different matter. When an application requests a synchronous write, it tells the file system: 'You need to commit this to non-volatile memory, <i>right now<\/i>, and until then, I can't do anything else.' Therefore, synchronous writes must be immediately committed to disk \u2014 and if this increases fragmentation or reduces throughput, so be it.<\/p>\n<p>ZFS handles synchronous writes differently than traditional file systems \u2014 instead of immediately writing them to conventional storage, ZFS commits them to a special storage area known as the ZFS Intent Log, or ZIL. The trick is that these writes <i>also<\/i> remain in memory, being aggregated together with regular asynchronous write requests, to later be flushed to storage as completely normal TXG (Transaction Groups).<\/p>\n<p>During normal operation, the ZIL is written to and never read again. When, after a few moments, the records from the ZIL are committed to the main storage in regular TXG from RAM, they are detached from the ZIL. The only time anything is read from the ZIL is during pool import.<\/p>\n<p>If a ZFS failure occurs \u2014 whether it\u2019s an OS failure or a power loss \u2014 when there is data in the ZIL, that data will be read during the next pool import (for example, after a system crash restart). Everything in the ZIL will be read, grouped into TXG, committed to the main storage, and then detached from the ZIL during the import process.<\/p>\n<p>One of the auxiliary classes vdev is called LOG or SLOG, a secondary LOG device. Its sole purpose is to provide the pool with a separate and, preferably, much faster vdev that has very high write resilience for storing ZIL, instead of storing ZIL on the main storage vdev. The ZIL itself behaves the same regardless of its storage location, but if the vdev with LOG has very high write performance, synchronous writes will occur faster.<\/p>\n<p>Adding a vdev with LOG to the pool does not <b>cannot<\/b> improve the performance of asynchronous writes \u2014 even if you force all writes to ZIL using <code>zfs set sync=always<\/code>, they will still be tied to the main storage in TXG in the same way and at the same pace as without the log. The only direct performance improvement is the latency of synchronous writes (as a higher log speed accelerates the execution of operations. <code>sync<\/code>).<\/p>\n<p>However, in an environment that already requires a lot of synchronous writes, the vdev LOG can indirectly speed up asynchronous writes and uncached reads. Offloading ZIL writes to a separate vdev LOG means less competition for IOPS in the primary storage, which somewhat boosts the performance of all read and write operations.<\/p>\n<h3>Snapshots<\/h3>\n<p>\nThe copy-on-write mechanism is also a necessary foundation for atomic ZFS snapshots and incremental asynchronous replication. In an active file system, there is a tree of pointers marking all records with the current data \u2014 when you take a snapshot, you simply create a copy of this pointer tree.<\/p>\n<p>When a record is overwritten in an active file system, ZFS first writes a new version of the block to unused space. It then detaches the old version of the block from the current file system. But if any snapshot references the old block, it remains unchanged. The old block actually will not be reclaimed as free space until all snapshots referencing that block are destroyed!<\/p>\n<h3>Replication<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/647fe6cc348861b653b004640244cf88.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>My Steam library in 2015 occupied 158 GiB and included 126,927 files. This is quite close to the optimal situation for rsync \u2014 ZFS replication over the network was 'only' 750% faster.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/2849be8d2dc5c9f30f23c3bbc20e9022.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>In the same network, replicating a 40-gigabyte Windows 7 virtual machine image is a completely different story. ZFS replication occurs 289 times faster than rsync\u2014or 'only' 161 times faster if you're savvy enough to invoke rsync with the --inplace key.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"Basics of ZFS: storage system and performance\" src=\"\/wp-content\/uploads\/2020\/06\/9a57e4faa0eaf0f687ae24b965a1bf81.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>When a virtual machine image scales, rsync issues scale with it. A size of 1.9 TiB isn't that large for a modern virtual machine image\u2014but it's large enough that ZFS replication turns out to be 1148 times faster than rsync, even with the rsync --inplace argument.<\/i><\/p>\n<p>Once you understand how snapshots work, grasping the essence of replication becomes straightforward. Since a snapshot is just a tree of pointers to records, it follows that when we create a <code>zfs send<\/code> snapshot, we send both this tree and all related records. When we pass this <code>zfs send<\/code> downward API support (simultaneously with this in <code>zfs receive<\/code> to the target object, it writes both the actual block contents and the tree of pointers referencing the blocks into the target dataset.<\/p>\n<p>Things get even more interesting on the second <code>zfs send<\/code>. Now we have two systems, each containing <code>poolname\/datasetname@1<\/code>, and you take a new snapshot <code>poolname\/datasetname@2<\/code>. Thus, in the source pool, you have <code>datasetname@1<\/code> and <code>datasetname@2<\/code>, while the target pool only has the first snapshot for now. <code>datasetname@1<\/code>.<\/p>\n<p>Since we have a shared snapshot between the source and the target, we can create an <code>datasetname@1<\/code>incremental <i>on top of it. When we tell the system<\/i> <code>zfs send<\/code> zfs send -i poolname\/datasetname@1 poolname\/datasetname@2 <code>, it compares the two trees of pointers. Any pointers that exist only in<\/code>, obviously point to new blocks \u2014 hence we will need the content of those blocks. <code>@2<\/code>On the remote system, processing the incremental<\/p>\n<p>is equally simple. First, we write down all the new records included in the stream <code>send<\/code> , and then we add pointers to these blocks. Voila, we have <code>send<\/code>in the new system! <code>@2<\/code> Asynchronous incremental replication with ZFS is a massive improvement over earlier methods that did not use snapshots, such as rsync. In both cases, only changed data is transferred \u2014 but rsync has to gather data from both sides to check the checksum and compare it first. In contrast, ZFS replication reads nothing except the trees of pointers \u2014 and any blocks that are not represented in the shared snapshot.<\/p>\n<p>Asynchronous incremental ZFS replication is a huge improvement over earlier methods not based on snapshots, such as rsync. In both cases, only the changed data is transferred\u2014but rsync has to read from disk on both sides to check the checksum and compare it. <i>read<\/i> In contrast, ZFS replication reads nothing but the pointer trees\u2014and any blocks not represented in the common snapshot.<\/p>\n<h3>Built-in Compression<\/h3>\n<p>\nThe copy-on-write mechanism also simplifies the built-in compression system. In traditional file systems, compression is problematic\u2014both the old and new versions of modified data reside in the same space.<\/p>\n<p>If we consider a fragment of data in the middle of a file that starts its life as a megabyte of zeros from 0x00000000 onward, it can be easily compressed down to one sector on disk. But what happens if we replace that megabyte of zeros with a megabyte of incompressible data, such as JPEG or pseudorandom noise? Surprisingly, this megabyte of data would require not one, but 256 sectors of 4 KiB each, while only one sector is reserved at that point on the disk.<\/p>\n<p>ZFS does not have this problem, as modified records are always written to unused space\u2014the original block occupies only one 4 KiB sector, while the new record will take 256, but this is not an issue\u2014the recently modified fragment from the 'middle' of the file would be written to unused space regardless of whether its size changed or not, so this is a normal situation for ZFS.<\/p>\n<p>Built-in compression in ZFS is disabled by default, and the system offers pluggable algorithms\u2014currently including LZ4, gzip (1-9), LZJB, and ZLE.<\/p>\n<ul>\n<li><b>LZ4<\/b> \u2014 is a streaming algorithm that offers extremely fast compression and decompression with performance gains for most use cases\u2014even on fairly slow CPUs.\n<\/li>\n<li><b>GZIP<\/b> \u2014 a venerable algorithm that is known and loved by all Unix system users. It can be implemented with compression levels 1-9, with increasing compression ratios and CPU usage as you approach level 9. The algorithm is well-suited for all text (or other highly compressible) use cases, but otherwise can often strain CPU resources\u2014use it with caution, especially at higher levels.\n<\/li>\n<li><b>LZJB<\/b> \u2014 the original algorithm in ZFS. It is outdated and should no longer be used, as LZ4 outperforms it in every metric.\n<\/li>\n<li><b>ZLE<\/b> \u2014 Zero Level Encoding. It does not touch normal data at all, but compresses large sequences of zeros. Useful for entirely non-compressible datasets (like JPEG, MP4, or other already compressed formats), as it ignores non-compressible data but compresses unused space in the final records.<\/li>\n<\/ul>\n<p>\nWe recommend LZ4 compression for practically all use cases; the performance penalty when encountering non-compressible data is very small, and <i>increase<\/i> the performance for typical data is significant. Copying a virtual machine image for a new installation of the Windows operating system (a freshly installed OS, with no data inside yet) with <code>compression=lz4<\/code> was 27% faster than with <code>compression=none<\/code>, in <noindex><a rel=\"nofollow\" href=\"https:\/\/jrs-s.net\/2015\/02\/24\/zfs-compression-yes-you-want-this\/\">in this 2015 test.<\/a><\/noindex>.<\/p>\n<h1>ARC \u2014 Adaptive Replacement Cache.<\/h1>\n<p>\nZFS is the only modern file system known to us that uses its own reading cache mechanism rather than relying on the operating system's page cache to store copies of recently read blocks in RAM.<\/p>\n<p>Although the internal cache has its problems \u2014 ZFS cannot respond to new memory allocation requests as quickly as the kernel, so a new call <code>malloc()<\/code> for memory allocation may fail if it requires RAM currently occupied by the ARC. But there are compelling reasons to use an internal cache, at least for now.<\/p>\n<p>All known modern operating systems, including MacOS, Windows, Linux, and BSD, use the LRU (Least Recently Used) algorithm to implement page caching. This is a primitive algorithm that promotes a cached block 'up the queue' after each read and evicts blocks 'down the queue' as necessary to make room for new cache misses (blocks that had to be read from disk rather than from cache).<\/p>\n<p>Typically, the algorithm works fine, but in systems with large working data sets, LRU easily leads to thrashing \u2014 evicting frequently needed blocks to free space for blocks that will never be read from the cache again.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Adaptive_replacement_cache\">ARC<\/a><\/noindex>\u00a0\u2014 a considerably less naive algorithm that can be regarded as a 'weighted' cache. After each read of a cached block, it becomes slightly 'heavier' and harder to evict \u2014 and even after eviction, the block <i>is tracked<\/i> for a certain period of time. A block that has been evicted but then needs to be read back into the cache will also become 'heavier'.<\/p>\n<p>The end result of all this is a cache with a much higher hit ratio \u2013 the ratio between cache hits (reads performed from the cache) and misses (reads from disk). This is an exceptionally important statistic \u2013 not only are cache hits served orders of magnitude faster, but cache misses can also be served faster as the more cache hits there are, the fewer parallel requests to the disk and the lower the latency for those remaining misses that must be served from the disk.<\/p>\n<h1>Conclusion<\/h1>\n<p>\nAfter studying the core semantics of ZFS \u2014 how copy-on-write works, as well as the relationships between storage pools, virtual devices, blocks, sectors, and files \u2014 we are ready to discuss actual performance with real numbers.<\/p>\n<p>In the next section, we will examine the actual performance of pools with mirrored vdev and RAIDz, comparing them to each other as well as to traditional Linux kernel RAID topologies that we have explored. <noindex><a rel=\"nofollow\" href=\"https:\/\/arstechnica.com\/information-technology\/2020\/04\/understanding-raid-how-performance-scales-from-one-disk-to-eight\/\">earlier<\/a><\/noindex>.<\/p>\n<p>Initially, we wanted to look at just the basics \u2014 the ZFS topologies themselves \u2014 but after <i>that<\/i> we will be prepared to talk about more advanced configuration and tuning of ZFS, including the use of auxiliary types of vdev such as L2ARC, SLOG, and Special Allocation.<br \/>\n<br \/>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/504692\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u042d\u0442\u043e\u0439 \u0432\u0435\u0441\u043d\u043e\u0439 \u043c\u044b \u0443\u0436\u0435 \u043e\u0431\u0441\u0443\u0434\u0438\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0432\u043e\u0434\u043d\u044b\u0435 \u0442\u0435\u043c\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0430\u0448\u0438\u0445 \u0434\u0438\u0441\u043a\u043e\u0432 \u0438 \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 RAID. \u0412\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445 \u043c\u044b \u0434\u0430\u0436\u0435 \u043f\u043e\u043e\u0431\u0435\u0449\u0430\u043b\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u043d\u043e\u0433\u043e\u0434\u0438\u0441\u043a\u043e\u0432\u044b\u0445 \u0442\u043e\u043f\u043e\u043b\u043e\u0433\u0438\u0439 \u0432 ZFS. \u042d\u0442\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u043e\u043a\u043e\u043b\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0435\u0439\u0447\u0430\u0441 \u0432\u043d\u0435\u0434\u0440\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0432\u0441\u044e\u0434\u0443: \u043e\u0442 Apple \u0434\u043e Ubuntu. \u041d\u0443 \u0447\u0442\u043e \u0436, \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0441\u0430\u043c\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0434\u0435\u043d\u044c \u0434\u043b\u044f \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":83583,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-83582","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u042d\u0442\u043e\u0439 \u0432\u0435\u0441\u043d\u043e\u0439 \u043c\u044b \u0443\u0436\u0435 \u043e\u0431\u0441\u0443\u0434\u0438\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/osnovy-zfs-sistema-hraneniya-i-proizvoditelnost\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041e\u0441\u043d\u043e\u0432\u044b ZFS: \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u042d\u0442\u043e\u0439 \u0432\u0435\u0441\u043d\u043e\u0439 \u043c\u044b \u0443\u0436\u0435 \u043e\u0431\u0441\u0443\u0434\u0438\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/osnovy-zfs-sistema-hraneniya-i-proizvoditelnost\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-06-01T17:42:21+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-06-01T17:42:21+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47 ZFS Basics: Storage and Performance | ProHoster","description":"This spring we already discussed some.","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/osnovy-zfs-sistema-hraneniya-i-proizvoditelnost","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041e\u0441\u043d\u043e\u0432\u044b ZFS: \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c | ProHoster","og:description":"\u042d\u0442\u043e\u0439 \u0432\u0435\u0441\u043d\u043e\u0439 \u043c\u044b \u0443\u0436\u0435 \u043e\u0431\u0441\u0443\u0434\u0438\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435.","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/osnovy-zfs-sistema-hraneniya-i-proizvoditelnost","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-06-01T17:42:21+00:00","article:modified_time":"2020-06-01T17:42:21+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"83582","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 15:14:37","updated":"2022-09-28 10:00:57","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/83582","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=83582"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/83582\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/83583"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=83582"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=83582"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=83582"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}