System plików ZFS został opracowany przez firmę Sun dla systemu Solaris. ZFS to 128-bitowy system plików, który obsłuży do 256 kwadrylionów ZB danych (1ZB = miliard TB). Prace nad ZFS rozpoczęły się w 2001 roku, natomiast oficjalnie poinformowano o tym pod koniec 2004 roku. W 2005 roku po raz pierwszy system ZFS został zaprezentowany dla OpenSolaris, a rok później w 2006 roku został zintegrowany z systemem Solaris w wersji 10. Warto zauważyć, że między czasie firma NetApp pozwała firmę Sun do sądu oskarżając o wykorzystanie siedmiu patentów. Spór w sądzie między firmami trwał do momentu, aż Sun w 2010 roku został przejęty przez firmę Oracle. Po przejęciu Oracle podpisało porozumienie z NetApp i od tego momentu Oracle postanowił udostępnił kod ZFS na licencji open sorce.
Dlaczego inne systemy plików są niedoskonałe?
Zanim przejdziemy do szczegółowego opisywania zalet systemu ZFS, należy wypunktować z czym nie radzą sobie pozostałe systemy plików. Przede wszystkim jest to brak narzędzia do wyeliminowania cichego uszkodzenia danych, które może być spowodowane przez uszkodzony dysk twardy, wadliwy kontroler RAID, źle napisany sterownik, czy też firmware lub uszkodzony laser. Dobrze przeczytaliście, uszkodzony laser może powodować błędy w zapisie danych. Przykładowo w środowisku Fibre Channel, polega to na tym, że system operacyjny zapisuje dane na macierz SAN przez sieć i protokół FC. Niestety zanim trafią one na macierz zostają po drodze uszkodzone przez laser nadajnika karty konwergentnej zainstalowanej w serwerze. Obecne systemy plików nie mają narzędzia, które potrafiłyby wykryć ewentualne błędy w zapisie.
Innym problemem są wszelkiego rodzaju ograniczenia tj. wielkość wolumenu, wielkość pliku, liczby plików w jednym katalogu, czy ilości migawek. Nie mamy także możliwości migracji między różnymi platformami (x86, SPARC, PowerPC, ARM), bez ponownej synchronizacji całego systemu plików.
Okazuje się, że samo zarządzanie systemami plików nie jest łatwe; przykładowo dla CIFS, NFS, czy iSCSI musimy wykorzystać różne narzędzia. Na problemy w zarządzaniu ma także wpływ konieczność tworzenia wolumenów, partycji i labelek. Do tego wszystkiego można dodać wolne działanie, wykorzystywanie stałego bloku danych, długą rozbudowę i odbudowę systemu po awarii czy długi czas tworzenia nowych wolumenów.
Założenia dla nowego systemu plików
Projektantom systemu ZFS przyświecało jedno motto
„Stworzony, żeby zapewnić integralność danych”
System ZFS został zaprojektowany od podstaw, przez co wyeliminował 20 letnie przestarzałe założenia, jakie wykorzystują inne systemy plików. Takie podejście miało na celu uprościć zarządzanie dużymi zbiorami danych. Dodatkowo operacja na zbiorach miała być możliwa podczas, gdy te są on-line.
W standardowych systemach plików wykorzystuje się tzw. wolumeny. Jest to warstwa, która pośredniczy w komunikacji między system plików, a grupą dysków. Jest to spowodowane tym, że większość systemów plików z założenia miała zarządzać tylko pojedynczym dyskiem. Jednak rozwój technologii sprawił, że dyski zaczęto łączyć w grupy, w celu zwiększenia wydajności oraz niezawodności. Takie podejście dało dwie możliwości: trudną, czyli przebudowę całego systemu plików od podstaw, lub łatwą, a więc dodanie kolejnej warstwy tzw. wolumenu, której zadaniem było pośredniczenie w komunikacji między systemem plików, a dyskami. Niestety nowa warstwa nie rozwiązała wszystkich problemów. Np. nie jest w stanie obsłużyć jednocześnie więcej niż jedną grupę RAID, co przekłada się na ograniczenie wielkości takiego wolumenu oraz jego wydajności.
Storage pool
W systemie ZFS mamy do dyspozycji tzw. „pulę dyskową”, która reprezentuje powierzchnię dysków i grup RAID do niej przypisanych. Dzięki takiemu podejściu uzyskujemy praktycznie nieograniczone możliwości rozbudowy oraz zdecydowanie lepszą wydajność.
W zwykłym systemie plików, gdy zastosujemy dysk SATA 7200, który umożliwia zapis z prędkością 150MB/s, uzyskamy wydajność na poziomie możliwości dysku tj. 150MB/s. W momencie, gdy dodamy drugi dysk to wtedy musimy stworzyć na nim drugi niezależny system plików i wtedy nadal, maksymalnie co możemy uzyskać to 150MB/s. W ZFS możemy zwiększyć to pasmo poprzez dodanie dysków do tej samej puli dyskowej i uzyskamy 300MB/s.
Oczywiście na zwykłym systemie można skonfigurować RAID w celu zwiększenia wydajności, np. RAID 0 i wtedy osiągniemy 300 MB/s, tylko, że przy takim podejściu ZFS do tej samej puli dyskowej może podłączyć kilka grup RAID 0, co sprawi, że wydajność będzie zdecydowanie wyższa. Wynika to z tego, że standardowy system plików nie obsłuży w tym samym czasie więcej niż jedną grupę RAID. Co więcej, ZFS umożliwia dodawanie do tej samej puli dyskowej różnych grup RAID oraz dysków o różnej specyfikacji dyskowej, co zdecydowanie zwiększa elastyczność takiego systemu.
Żeby tego było mało, w konfiguracji puli dyskowej możemy skonfigurować ilość kopii dla każdego bloku. Mogą to być odpowiednio jedna, dwie lub trzy kopie. Co za tym idzie, zamiast konfigurować dwie grupy RAID 0 i dodawać je do puli dyskowej, po prostu konfigurujemy RAID Z2 na cztery dyski i nadal mamy wydajność 600 MB/s, a z 4 dysków, awarii mogą ulec 2. W przykładzie zwykłego systemu plików awaria jednego dysku powoduje całkowitą utratę danych.
Kolejną zaletą stosowania pul dyskowych jest dynamiczna alokacja przestrzeni. W standardowych systemach plików musimy na starcie zdecydować jaka będzie wielkość partycji. Powoduje to, że często przypisuje się duże wartości, tak żeby w przyszłości nie okazało się, że zabraknie nam miejsca. Niestety takie podejście powoduje, że często w praktyce wykorzystane jest tylko 30% przypisanej przestrzeni, a pozostałe 70% jest po prostu zmarnowane. W ZFS przestrzeń jest alokowana dynamicznie, co za tym idzie nie musimy się martwić, w momencie tworzenia systemu jaką przypisać mu wielkość oraz co chyba ważniejsze, nie doświadczymy jak w przypadku zwykłych systemów niewykorzystanych powierzchni danych.
W przypadku ZFS, tworzenie systemu plików odbywa się od razu i równie szybko odbywa się rozbudowa puli dyskowej. W zwykłych systemach plików, zawsze musimy czekać na to, aż system sformatuje dyski, a następnie zsynchronizuje bloki danych jeżeli skonfigurowaliśmy grupę RAID. Dodanie nowego dysku do grupy RAID ponownie wymusza przejście procesu synchronizacji.
W przypadku awarii dysku, zwykłe systemy ponownie synchronizują cały wolumen blok po bloku, bez weryfikowania czy na danym bloku znajdowały się dane, czy nie. ZFS synchronizuje tylko bloki, na których faktycznie znajdowały się dane, co znacznie przyspiesza proces odbudowy. Przykładowo, gdy mamy system plików ZFS o wielkość 1TB, na którym było zapisane 250GB danych, to odbudowa takiego systemu po awarii dysku odbywa się 382% szybciej niż w przypadku standardowego systemu plików.
Warstwy komunikacji
Jak widać na powyższym diagramie, zarówno ZFS jak i standardowe systemy plików posiadają trzy warstwy komunikacji. W przypadku zwykłych systemów plików operacje od górnej do dolnej warstwy odbywają się na blokach, każda operacja jest zapisywana do dziennika, który jest wykorzystywany przy synchronizacji systemu plików po wystąpieniu awarii. Niestety takie podejście nie rozwiązuje problemu „dziury zapisu dla RAID 5”.
ZFS realizuje procedurę komunikacji w oparciu o obiekty i tak pierwsza warstwa ZPL ma za zadanie przetłumaczyć operacje wykonywane na danych, na zmiany wykonywane na obiektach i połączenie ich w jedną transakcję. Kolejna warstwa DMU ma za zadanie połączyć otrzymane transakcje w grupy transakcji i przesyłać tak stworzone grupy do warstwy SPA, której zadaniem jest wykonanie operacji zapisanych w otrzymanych transakcjach. W tym przypadku najważniejsze zmiana w stosunku do standardowego systemu plików, to wykorzystanie transakcji, takie podejście gwarantuje, że system plików jednocześnie wykona wszystkie zmiany na obiektach zapisane w transakcji, albo nie wykona żadnej. Dzięki temu w momencie wystąpienia awarii system nie musi się ponownie synchronizować, jak to jest w zwykłych systemach plikowych, oprócz tego nie ma potrzeby zapisywania dziennika zmian dla każdej operacji, jak to ma miejsc w innych systemach plików, co ma duży wpływ na wydajność.
Zunifikowany system plików
ZFS nie potrzebuje różnych narzędzi do świadczenia usług NFS, CIFS czy iSCSI, co więcej natywnie dostarczone funkcjonalności takie jak migawki, kompresja, szyfrowanie, deduplikacja czy klonowanie są dostępne dla wszystkich zbiorów danych utworzonych na puli dyskowej.
Transakcje Copy-On-Write
Powyższy rysunek pokazuje w jaki sposób ZFS zapisuje dane co przekłada się na lepszą wydajność oraz wyeliminowanie „dziury zapisu dla RAID 5”. Ogólnie zasada jest taka, że nowe dane nigdy nie nadpisują aktualizowanych danych, nowe dane zawsze są zapisywane na nowych pustych blokach. Dzięki temu, że są to nowe bloki to zapis jest zawsze sekwencyjny, a nie losowy.
Na obrazku numer 1 widać stare dane, na 2 zaczął się zapis nowych danych gdzie najpierw zapisywane są bloki danych. Na obrazku 3 ZFS kontynuuje zapis nowych danych, tym razem aktualizowane są bloki sum kontrolnych nowych danych. Stare dane pozostają nadal nie naruszone, dopiero na obrazku 4 widać, że zapis nowych danych przebiegł pomyślnie i w tym momencie stare dane zostają skasowane z dysków.
W przypadku standardowego systemu plików, stare dane są od razu nadpisywane przez nowe. Więc jeżeli proces zapisu zostanie przerwany przez awarię zasilania, przykładowo na etapie 3 obrazka, gdzie udało się zapisać bloki z danymi, a nie dokonano aktualizacji sum kontrolnych, to wtedy po uruchomieniu systemu nie mamy dostępu do starych danych, bo zostały one częściowo nadpisane. Najgorsze jest to, że system plików nie wykryje tego błędu, bo w dzienniku zdarzeń będzie informacja, że bloki danych zostały zapisane prawidłowo, a niestety dziennik nie weryfikuje zapisu sum kontrolnych. Taka sytuacja powoduje że po awarii system uruchomi się i zsynchronizuje się, wykorzystując błędne bloki, które uszkodzą cały system plików. Taki efekt nazywamy „dziurą zapisu RAID5”.
Migawki
System plików ZFS umożliwia wykonywania migawek, których ilość w praktyce jest praktycznie nieograniczony. Migawki w ZFS w porównaniu do tych w standardowych systemach plików nie obciążają systemu i zajmują mało miejsca, bo przechowują tylko deltę zmian. Wykonanie migawki nie oznacza, że od razu przenoszone są do niej danych, dane w migawce są zapisywane dopiero w momencie, gdy oryginalne dane zostają nadpisane.
Ciche uszkodzenie danych
Okazuje się, że temat jako pierwszy na świecie poruszyło laboratorium CERN. Otóż w CERN podejrzewano, że dane, które zapisywano na 3000 macierzach są podejrzane. Co zrobiono? Napisano program FSPro, którego zadaniem było zapisywanie na macierzach pliku 1GB podzielonego na bloki 1MB, które zapisywano w odstępach 1 sekundy. Następnie odczytywano plik 1GB również w blokach 1MB w odstępach 1 sekundy. Ponieważ było wiadomo, co było zapisane, to oczywistym było jakiego odczytu należy się spodziewać. Okazało się, że po 3 tygodniach testów wykryto, aż 152 przypadki cichego uszkodzenia danych.
Integralność danych – wykrycie cichego uszkodzenia danych
ZFS potrafi wykryć ciche uszkodzenie danych podczas gdy standardowe systemy potrafią wykryć tylko uszkodzenie pojedynczego bitu w bloku danych. Dlaczego tak się dzieje?
Głównym problemem jest miejsce zapisu sumy kontrolnej. Otóż standardowe systemy plików zapisują bloki danych i ich sume kontrolną na tym samym bloku danych w tym samym czasie. Więc jeżeli w obrębie tego bloku uszkodzi się pojedynczy bit to przy odczycie danych z tego bloku system plików jest w stanie wykryć uszkodzone dane. Problem pojawia się przy zapisie widmo, zapisie na błędny blok lub przy odczycie błędnego bloku itp.
Na czym polega zapis widmo? Przykładowo zapisujemy na blok danych stan naszego konta, niech to będzie 5000 PLN oraz ich sumę kontrolną. Następnie system prosi o aktualizację tej kwoty do 10000PLN oraz jej sumy kontrolnej. Więc wysyła prośbę do dysku o aktualizację tego bloku i zwrotnie otrzymujemy informację, że aktualizacja została wykonana. W praktyce dysk jej nie zrobił. W tym momencie, gdy system ponownie odczyta blok, to otrzyma informacje, że stan konta to 5000 PLN, oczywiście sprawdzi sumę kontrolną w celu weryfikacji czy dane nie są uszkodzone, ale ponieważ suma też nie została zapisana, to z punktu widzenia systemu dane są nie uszkodzone.
Jak to wygląda przy zapisie na błędny blok? Załóżmy, że sytuacja jest podobna: system prosi dysk o zapisanie danych na bloku o numerze 93, dane oczywiście zawierają stan naszego konta, tym razem będzie to 3000 PLN, po pewnym czasie, system prosi o aktualizację bloku 93, tym razem stan naszego konta ma mieć wartość 7000 PLN. Dysk wykonuje zapis i potwierdza go dla systemu plików. Tylko, że w praktyce, dysk zamiast zapisać dane na blok 93, to przez złe ustawienie głowicy zapisał je na bloku 72. Mimo iż dane zostały zapisane prawidłowo to znajdują się w złym sektorze dysku, a co za tym idzie dane na bloku 93 jak i ich suma nie zostały nadpisane. W momencie, gdy system odczyta dane z bloku 93 bo wie, że tam powinny być dane o stanie naszego konta, to z punktu widzenia integralności danych wszystko będzie ok, więc w tym momencie wyparuje nam z konta 4000 PLN.
Co zmieniono w ZFS, że potrafi on wykryć ciche uszkodzenie danych? Przede wszystkim ZFS osobno zapisuje bloki z danymi i osobno zapisuje sumy kontrolne. Dodatkowo ZFS wykorzystuje zgodnie z terminologią kryptografii samo weryfikujące się drzewo, więc dla sumy kontrolnej wykonywane są kolejne sumy i tak, aż do momentu, osiągnięcia najwyższego bloku w drzewie, zwanego także root blokiem. Warto wspomnieć, że sumy kontrolne są 256-bitowe i zapisywane są w metadanych systemu plików.
Jak ZFS radzi sobie z zapisem widmo? Gdy w ZFS zapisujemy stan naszego konta, który na początku wynosi 5000 PLN, to osobno zapisywany jest blok z danymi i osobno suma do metadanych i teraz jeżeli dokonamy aktualizacji, to zakładając, że dysk tak jak poprzednio mimo potwierdzenia nie zapisze bloku z danymi, to mimo wszystko zapisze nową sumę. Dzięki temu w momencie odczytu system wykryje, że suma nie będzie odpowiadała zapisanym danym, więc zostaną one uznane jako uszkodzone.
Podobna sytuacja ma się do zapisu na błędny blok. Przykładowo, jeżeli na blok 93 zapiszemy stan naszego konta, a suma zostanie zapisana do metadanych i następnie dokonamy aktualizacji, gdzie zapis danych zostanie wykonany na blok 72, zamiast na 93, to i tak suma kontrolna danych z aktualizacją zostanie zapisana prawidłowo do metadanych. Więc przy odczycie system jest w stanie zweryfikować, że dane w bloku 93, które nie zostały zaktualizowane, nie odpowiadają sumie.
Integralność danych – naprawa uszkodzonych danych
Skoro już wiemy w jaki sposób ZFS wykrywa uszkodzone dane, to teraz warto napisać jak je naprawia. Poniżej rysunek, który pokazuje co dzieje się z uszkodzonymi danymi w innych systemach plikowych. Jak widać, mimo iż dane są uszkodzone to nadal są przetwarzane.
W przypadku ZFS wygląda to inaczej. Naprawa danych odbywa się w czasie rzeczywistym, dzięki narzędziu RAID Scrubbing, które jest odpowiednikiem narzędzia FSCK dla innych systemów. Główna różnica polega na tym, że FSCK można uruchomić tylko na odmontowanym wolumenie, a RAID Scrubbing działa on-line.
Jak widać na powyższym rysunku w momencie, gdy z dysków zostanie odczytany uszkodzony blok, to ZFS go wykryje, po wykryciu od razu naprawi go przy pomocy kopi tego bloku zapisanej na innych dyskach i dopiero wtedy udostępni dane z tego bloku dla aplikacji.
Dynamiczna wielkość bloków
System plików ZFS został tak zaprojektowany, aby dynamicznie dobierał wielkość bloków do danych, które są na niego zapisywane. Wielkości bloków w ZFS znajdują się w przedziale od 512B do 128 K. Dlaczego dynamiczna wielkość bloków jest taka ważna? Gdy mamy zwykły system plików, ze stałymi blokami 4K i zapisujemy numer telefonu w pliku txt, który zajmuje niecałe 47B to tracimy mimo wszystko sporo przestrzeni.
Gdy ten sam plik txt z numerem telefonu zapiszemy na mniejszy blok, przykładowo 512B, to wtedy tracimy zdecydowanie mniej przestrzeni.
Innym przykładem może być plik, który zajmuje 17GB, niech to będzie film. W momencie gdy zapiszemy go na blokach 4K, to wtedy musimy zapisać go na 4456448 bloków. Gdy ten sam plik zapiszemy na blokach 128K, to wtedy będzie to tylko 139264 bloków, więc będzie to 35 tysiąca razy mniej operacji I/O, co przekłada się na wydajność systemu. Oczywiście ktoś powie, że w takim przypadku można stosować jeszcze większe bloki, przykładowo 100MB, wtedy przy tak dużym pliku będzie jeszcze mniej bloków do zapisu. Jednak okazuje się, że to nie jest takie proste, bo co w przypadku, gdy będziemy chcieli edytować 100KB z tego filmu, wtedy musielibyśmy odczytać, aż 100MB blok. Twórcy ZFS wykonali sporo testów, które potwierdziły, że zakres bloków jakie zaproponowali są optymalnie dobrane.
Odporność na awarie
Jeżeli mowa o systemie plików, to najprościej przedstawić go w postaci trójkąta, na samej górze znajdują się metadane globalne, po środku są metadane lokalne, a na samym dole znajdują się faktyczne dane. Jeżeli chodzi o zajętość, to same metadane zajmują około 1% powierzchni.
W przypadku awarii standardowego systemu plików dane można odczytać dopiero w momencie gdy 100% danych zostanie zsynchronizowanych, w przypadku uszkodzenia pojedynczego bloku metadanych tracimy dostęp do wszystkich danych.
W przypadku ZFS odbudowa systemu zawsze zaczyna się od góry, od najważniejszych bloków tzn. od metadanych. Dzięki temu możemy jeszcze w czasie trwania odbudowy mieć dostęp do części danych. W momencie, gdy nie uda się odzyskać 100% danych, to przynajmniej mamy dostęp do danych, które nie zostały uszkodzone.
Oczywiście projektanci systemu plików ZFS stwierdzili, że głupio by było straci kilka GB danych, tylko dlatego, że uszkodził się jeden blok, na którym były zapisane metadane, szczególnie, że zajmują one jedynie 1% powierzchni. Dlatego stworzono tzw. bloki Ditto i tak lokalne metadane mają 2 kopie danych, a globalne bloki danych 3 kopie. W przypadku, gdy mamy RAID 1 dodany do puli dyskowej, to wtedy lokalne metadane mają 4 kopie danych, a globalne kopie mają 6 kopi danych. Podsumowując ZFS jest w stanie przetrwać awarie, których nie przetrwa żaden inny system plików.
Inteligencja systemu plików ZFS
System plików ZFS potrafi analizować ruch danych i wyszukiwać w nim konkretnych wzorców zachowań, które po rozpoznaniu wykorzystuje do zwiększenia wydajności. Jeżeli na zwykłym systemie plików, ten sam film będzie w tym samym czasie odtwarzało trzech użytkowników, to taki odczyt zostanie potraktowany jak odczyt w trybie losowym, który ma gorszą wydajność.
System plików ZFS w takim przypadku zamiast traktować ten odczyt jako losowy, potrafi wykryć wzór, który mówi, że w praktyce są to trzy niezależne odczyty sekwencyjne, mimo iż każdy użytkownik w danym momencie ogląda film w innym miejscu. Taka zdolność sprawia, że system ZFS idealnie sprawdza się do wykorzystywania w aplikacjach do streamingu mediów.
Dodatkowo ZFS potrafi w tym samym czasie analizować ruch w dwóch wymiarach, czym sprawia, że można go stosować także z aplikacjami HPC.
ARC zamiast standardowego RAM
System plików ZFS w sposób specyficzny wykorzystuje pamięć RAM. W standardowych systemach działa to jak na poniższym rysunku tzn. w RAM-ie są przechowywane najbardziej aktualne dane, najstarsze zostają przenoszone na dyski twarde.
ZFS postanowił zreorganizować zasadę działania pamięci RAM. Podzielił ją na dwie części: pierwsza działa jak standardowa pamięć RAM, natomiast druga ma za zadanie przechowywać najczęściej wykorzystywane dane w celu przyspieszenia dostępu do nich. Jest to swego rodzaju „auto tiering”.
Funkcjonalność
Oprócz tego, że ZFS zapewnia integralność danych to dodatkowo obsługuje natywnie na najniższej warstwie funkcjonalności za które w innych systemach trzeba dużo zapłacić. Jest to deduplikacja bloków działająca w locie, SSD Cache dla odczytu i zapisu, kompresja danych na poziomie bloków, szyfrowanie zbiorów danych na poziomie bloków oraz możliwość klonowania zbiorów danych na poziomie bloków.
Podsumowanie
Mam nadzieję, że po przeczytaniu tego artykułu nie macie już wątpliwości jaki system plików powinniście wykorzystywać do przechowywania swoich cennych danych. Jeżeli szukasz, serwera NAS, który obsługuje ZFS to polecamy serwery QNAP z systemem QTS HERO.
Dodatkowo załączam plik testu systemu ZFS, który zawiera badania czteroosobowego zespołu z Uniwersytetu Wisconsin, który zadał sobie trud bardzo gruntownego przetestowania systemu plików ZFS symulując przy pomocy techniki fault injections zarówno błędy dysków twardych, jak i błędy pamięci. Poniżej podsumowanie badań, które jest najlepszym dowodem na to, że ZFS jest w stanie przetrwać awarie, które w przypadku EXT4 powoduje utratę danych.
We analyze a state-of-the-art file system, Sun Microsystem’s ZFS, by performing fault injection tests representative of realistic disk and memory corruptions [..] ZFS successfully detects all corruptions and recovers from them as long as one correct copy exists. The in-memory caching and periodic flushing of metadata on transaction commits help ZFS recover from serious disk corruptions affecting all copies of metadata.
Warto też obejrzeć poniższe wideo, które pokazuje jak odporny na wszelkiego typu awarie jest klaster macierzy oparty na ZFS i GlusterFS.