Dienstag, 4. November 2008

Mythbusting: $FOOFS + LVM = ZFS

Man hört es ja immer wieder wenn man ZFS erwähnt: "Das kann ich doch auch mit LVM machen!" oder "ZFS verletzt ja den ganzen Layergedanken, das gehört getrennt weils ja sonst total Bloatware ist". Damit möchte ich gerne mal in ein paar Punkten aufräumen, vor allem aber auch zeigen das diese Designentscheidung alles andere als willkürlich ist. Dazu werde ich 2 klassische ZFS Beispiele besprechen: Selbstheilung und Intelligentes Prefetching

Sehen wir uns erst einmal an wie ein Mirror auf herkömmliche Art und Weise angelegt ist:



Hier liegt eine klassische Trennung von Filesystem und Volumemanager vor. Das Filesystem hat keinerlei Ahnung das es auf einem Mirror arbeitet der Volumemanager liefert ihm einfach ein virtuelles Device und veranstaltet sein spiegeln unbemerkt vom Filesystem. Auf der anderen Seite kennt der Volumemanager sich aber auch nicht mit dem Filesystem aus, er arbeitet einfach nur mit abstrakten Daten die er wegschreibt und er nicht versteht da er keinerlei Bezug zum Filesystem hat.

ZFS ist hier in 3 Schichten aufgeteilt:



Dem ZFS Posix Layer (ZPL) welcher die normale Posix API zur Verfügung stellt (open,close,read,write etc) darunter liegt direkt das ZFS welches einzelne Transaktionen (ZFS arbeitet NUR mit Transaktionen, dass heißt das das Filesystem nie in einen inkonsistenten Zustand kommt) an die Data Management Unit (DMU) weitergibt welche viele Transaktionen zu einer großen zusammenfasst und der Storage Pool Allocator (SPA) welcher Kenntnis von den Platten (die in unserem Beispiel gespiegelt sind) hat.

Jetzt wollen wir als Beispiel auf einem Spiegel einen fehlerhaften Block haben welcher gelesen wird, sagen wir einfach mal es handelt sich hier um Metadaten welche durch äußere Einwirkungen (Erschütterung, Strahlung, statische Entladung etc) verändert wurden. Der Volumemanager hat hier keine Ahnung ob die Daten korrekt sind und reicht sie ans Filesystem weiter. Im schlimmsten Fall kommt es jetzt zu einer Kernelpanic im weniger schlimmen werden falsche Daten gelesen und die Applikation liefert falsche Ergebnisse oder stürzt ab. Da das Filesystem allerdings keinerlei Ahnung hat das es auf einem Mirror arbeitet kann es selbst wenn es bemerkt das die Daten falsch sind ja nicht wissen das evtl ein Mirror mit richtigen Daten existiert und keine korrekten Daten anfordern (da Volumemanager und Filesystem nun einmal voneinander getrennt sind).

Wie macht ZFS das nun? Als Erstes räumt das Design von ZFS mit dem immer noch verbreiteten Glauben auf das Prüfsummen teuer sind. Bei den heuten Rechnergeschwindigkeiten ist die Berechnung einer solchen Summe zeitlich gesehen zu vernachlässigen. Dies macht sich ZFS zu nutze und sichert JEDEN Block mit einer Prüfsumme (default 256-bit). ZFS erkennt also immer ob ein Block immer noch in dem gleichen Zustand auf der Platte liegt wie es ihn geschrieben hat.
Wir lesen nun den gleichen Block aus dem oberen Beispiel noch einmal. Durch die Prüfsumme erkennen wir das der Block falsch ist und da ZFS selber Kenntnis darüber hat das es auf einem Mirror arbeitet fordert es den gleichen Block von der anderen Platte erneut an. Dieser ist in unserem Beispiel korrekt worauf er an die Applikation weitergereicht wird während der andere fehlerhafte Block verworfen wird und mit dem korrekten von der anderen Platte automatisch überschrieben wird. Die Applikation merkt davon nicht das geringste. (Es ist sogar möglich eine der beiden Platte während eines Lese/Schreibvorgangs mit dd if=/dev/random zu überschreiben ohne das die Applikation fehlerhafte Daten zu sehen kriegt, gleichzeitig wird der Schaden den dd anrichtet transparent geheilt)



Hat man nur eine Festplatte zu Verfügung kann man durch zfs set copies=n filesystem veranlassen das alle Datenblöcke n-fach geschrieben werden. Tritt nun ein Fehler auf wird dieser genauso geheilt wie auf einem Mirror. Man kann so ein extra Filesystem für sehr sensible Daten absichern ohne mehrere Platten zur Verfügung zu haben (z.b. auf Notebooks).

Ein anderes beliebtes Beispiel ist der intelligente Prefetchmechanismus. Nehmen wir folgendes an: Auf einem Filesystem liegt eine Videodatei die gleichzeitig von mehreren Benutzern gelesen wird. Alles in allem sind dies sequentielle Lesezugriffe, da alle diese User jedoch eine andere Stelle der Datei lesen kann man hier mit der herkömmlichen Aufteilung kein sequentielles Pattern erkennen, hier kann also kein Prefetch stattfinden da nicht erkannt wird welcher Block als nächstes gelesen wird. Da ZFS allerdings den Userkontext hat kann es erkennen das es sich hier um mehrere sequentielle Reads handelt und dementsprechend optimieren für normale Filesysteme + Volumemanager bleibt dies aufgrund des mangelnden Kontexts eine zufällige Leseabfolge.

Dies sind nur ein paar Beispiele welche Vorteile das Zusammenlegen von Volumemanager und Filesystem hat, unter anderem kann man damit auch dynamische Stripes haben etc.

ZFS räumt mit Annahmen auf die inzwischen 20 oder 30 Jahre alt sind, es ist komplett neu entwickelt worden mit Blick auf die Computerwelt wie sie heute ist, in der Storagekapazitäten gigantische Ausmaße annehmen und Fehler aufgrund von großen Datendurchsatz sehr leicht auftreten können und möglichst transparent repariert werden sollten. Unter anderem hat ZFS auch die on-disk Struktur stark vereinfacht (Metadaten,inodes welche hier znodes heissen, Daten etc werden gleich behandelt) oder Vorgänge wie formatieren und partitionieren abgeschafft (wer will heute schon 100TB formatieren und auf derartigen Speichermengen noch mit grow und shrink rumhantieren ;) ).

Ergo: Myth BUSTED!

Keine Kommentare: