S3 ist kein Dateisystem, sondern eine Technik zur Dateispeicherung
(calpaterson.com)- Amazon S3 ist eine frühe Cloud-Technologie aus dem Jahr 2006, stark bei der Dateispeicherung, aber kein Dateisystem, das die Unix-Datei-API unverändert ersetzt
- Die Unix-Datei-API ist eher ein tiefes Modul mit einer schmalen Schnittstelle wie
open,read,write,seek,close, hinter der sich Buffering, Page Cache, Berechtigungen und IO-Scheduling verbergen - S3 wirkt mit
GetObjectundPutObjecteinfach, erlaubt überRangeaber nur partielles Lesen und unterstützt kein partielles Überschreiben - Datenbanken wie Postgres, SQLite, MySQL, MongoDB und Elasticsearch sind auf seitenweises Überschreiben angewiesen, weshalb es abseits sehr kleiner Datensätze kaum passt, SQLite- oder DuckDB-Dateien unverändert auf S3 zu legen
- Hohe Lese- und Schreibbandbreite sowie geringer Betriebsaufwand sind Stärken von S3, doch Einschränkungen wie fehlendes rename/move, langsame Listenabfragen, eine reine XML-API und das Fehlen einer lokalen Testumgebung müssen mitbedacht werden
S3 speichert Dateien, ist aber kein Dateisystem
- S3 ist eine frühe Cloud-Technologie aus dem Jahr 2006 und wurde entsprechend der damaligen Sprachregelung als „Object Store“ bezeichnet
- In der Praxis wird es weithin als Dateispeicher genutzt, aber es als „Amazon Cloud Filesystem“ zu verstehen, trifft nur teilweise zu
- Es eignet sich gut zum Speichern von Dateien, kann aber das Verhalten und die Erwartungen an klassische Dateisysteme nicht eins zu eins ersetzen
Unix-Datei-API und tiefe Module
- Der Kern der Unix-Datei-API lässt sich auf die folgenden fünf Aufrufe zusammenfassen
open(filepath): öffnet eine Dateifile.read(size=100): liest an der aktuellen Position und verschiebt die Position nach vornfile.write("hello, world"): schreibt an der aktuellen Position und verschiebt die Position nach vornfile.seek(94): bewegt die Position zu einem bestimmten Bytefile.close(): schließt die Datei
- Diese Aufrufe gehören zum Kern der gesamten Systemaufrufe und kommen den minimal nötigen Funktionen zum Lesen und Schreiben von Dateien nahe
- Weil hinter der schmalen Schnittstelle viel Verarbeitung stattfindet, kann man die Unix-Datei-API als tiefes Modul (deep module) betrachten
- Buffering und Page Cache
- Umgang mit Fragmentierung
- Rechtemanagement
- IO-Scheduling
- Auch von Funktionen wie Wear Levelling auf SD-Karten profitieren Nutzer, ohne sich direkt darum kümmern zu müssen
Flache Module, YAML und ORM
- Flache Module haben im Verhältnis zu dem, was sie leisten, eine relativ große API-Oberfläche
- Ein heutiger Hinweis auf flache Module ist oft, wenn die Schnittstelle YAML ist
- YAML wirkt wie eine Markup-Sprache, wird aber in der Praxis als wiederverwendbare Syntax verwendet, auf die sich fast beliebige Semantik legen lässt
- Im DevOps-Bereich funktioniert YAML oft wie eine „Programmiersprache“
- Wenn eine YAML-Minisprachleife Wiederholungsstrukturen bietet, ist Turing-Vollständigkeit möglich
- Flache Module sind nicht immer schlecht
- SQL-ORMs sind ihrem Wesen nach lecke Abstraktionen und ohne Verständnis von SQL schwer sinnvoll zu nutzen
- In manchen Fällen kann ein flaches Modul die bestmögliche Form sein
- Unter gleichen Bedingungen ist ein tieferes Modul besser
Die S3-API ist einfach, aber nicht die Datei-API
- Die Unix-Datei-API hat sich Anfang der 1970er etabliert; aus Kompatibilitätsgründen blieb die Schnittstelle erhalten, während sich die interne Implementierung mehrfach änderte
- Amazon S3 implementiert die Unix-Dateisystem-API nicht neu
- Die Grundoperationen von S3 entsprechen der Unix-Datei-API nur teilweise
GetObject(Bucket, Key, Range=None): liest das gesamte Objekt oder einen Teil davonPutObject(Bucket, Key): schreibt das gesamte Objekt
- Es gibt zwar das zusätzliche Konzept eines Buckets, aber gemessen am Verhältnis von Funktionalität zu Schnittstelle ist S3 sogar einfacher als die Unix-Datei-API
- Der entscheidende Unterschied ist das Fehlen von partiellem Überschreiben
- Über das
Range-Argument vonGetObjectlässt sich ein Teil eines Objekts lesen - Es ist jedoch nicht möglich, nur einen Teil eines Objekts zu überschreiben
- Überschreiben geht nur auf Ebene der gesamten Datei
- Über das
- Deshalb passt S3 nur für einen Teil der bisherigen Datei-Anwendungsfälle wirklich gut
Datenbanken lassen sich nicht einfach unverändert auf S3 portieren
- Viele Datenbanken speichern ihre Daten in Dateien auf einem Dateisystem
- Postgres hält pro Tabelle 2–3 Dateien sowie diverse Verwaltungsdateien vor
- SQLite ist dafür bekannt, alle Daten in einer einzelnen Datei zu speichern
- MySQL, MongoDB und Elasticsearch speichern Daten ebenfalls in Dateien
- Das Problem ist, dass Datenbanken meist auf partiellem Überschreiben auf Seitenebene basieren
- Daten werden typischerweise in Seiten von 4 KB oder 8 KB gespeichert
- In einer Heap-Datei können Tausende solcher Seiten liegen
- Zur Ablage benötigter Daten werden Seiten teilweise überschrieben
- Legt man eine SQLite-Datenbank auf S3, müsste bei jedem Schreibvorgang die gesamte Datenbankdatei neu geschrieben werden
- S3 kann große Schreibvorgänge schnell verarbeiten, aber außer bei den allerkleinsten Datensätzen ist eine Strategie, jedes Mal die komplette Datei zu überschreiben, kaum tragfähig
- Wenn die Datenbankdatei jedes Mal neu geschrieben wird, lässt sich auch die vom Datenbankentwickler aufgebaute Transaktionsintegrität nur schwer nutzen
- Auf S3 gewinnt der letzte Schreibvorgang
Was S3 gut kann und was nicht
- Eine Stärke von S3 ist die sehr hohe Bandbreite beim Lesen und Schreiben
- Es ist nicht schwer, Berichte über mehr als 10 GB/s beim Lesen oder Schreiben auf S3 im Internet zu finden
- Es gab auch Erfahrungen, bei denen Schreibvorgänge auf S3 das Büronetzwerk eines Finanzkunden vollständig ausgelastet haben
- Neben dem Fehlen von partiellem Überschreiben gibt es weitere Einschränkungen im Vergleich zu einem Dateisystem
- S3 kennt keine rename- oder move-Operation
- Umbenennen erfolgt über
CopyObjectund anschließendDeleteObject CopyObjectbenötigt lineare Zeit proportional zur Dateigröße- Hat man viele Dateien an die falsche Stelle geschrieben, ist das Zurückrollen sehr langsam
- Umbenennen erfolgt über
- Das Auflisten von Dateien ist langsam
- Die Lese- und Schreibbandbreite ist sehr hoch, aber das Auflisten gespeicherter Einträge ist deutlich langsamer
- Es kann sogar langsamer sein als ein langsames lokales Dateisystem
- Dafür ist der Betriebsaufwand geringer als bei einem Dateisystem
- Man gibt nur Bucket und Key-Namen an, den Rest übernimmt die Cloud
- Wiederkehrende Aufgaben wie Backups, Offsite-Replikation und Provisionierung werden reduziert
- Provisionierung betrifft nicht nur Kapazität, sondern auch IO-Operationen
Bei Schnittstellen zwischen Organisationen sind tiefe Module noch wichtiger
- Dass S3 die erste populäre Cloud-API war, hängt auch mit den Vorteilen tiefer APIs zusammen
- Tiefe APIs helfen dabei, Komplexität zwischen Modulen innerhalb eines Systems zu verbergen, und sind in kostspieligen Beziehungen wie der Interaktion zwischen zwei Unternehmen noch wichtiger
- Die Verbindung von Computersystemen zwischen Unternehmen wurde traditionell als Integration bezeichnet und fast als Synonym für Schmerz behandelt
- Große Enterprise-Software wie SAP ist kein tiefes Modul
- Fast die gesamte Organisation muss SAP verstehen
- Es braucht laufende Abstimmung mit bestehenden Arbeitsweisen
- SAP-Integrationsprojekte sind teuer, riesig und scheitern immer wieder
- Die interne Komplexität von S3 ist nicht unbedingt geringer als die einer SAP-Installation
- Amazon nannte S3 zwar „Simple Storage Service“, aber die tatsächliche Komplexität von S3 ist hoch
- Dazu gehören Queueing-Theorie, IO-Contention, Sharding und viele Probleme, die Dateisysteme ebenfalls lösen müssen
- Das „simple“ bei S3 steht weniger für echte Einfachheit als für eine tiefe Schnittstelle
Passende Ausnahmen für S3 und verbleibende Grenzen
- Damit wird nicht ausgeschlossen, dass S3 für bestimmte Anwendungsfälle zu teuer sein kann
- Die Konzepte tiefer und flacher Module stammen aus John Ousterhouts A Philosophy of Software Design
- Es gibt auch Datenbanken, die von Anfang an dafür entworfen wurden, die S3-API als Storage-Layer zu nutzen
- Snowflake ist ein solches Beispiel
- Das ist aber keine transparente Portierung, sondern erfordert frühe Architekturentscheidungen
- Snowflake hatte diese Entscheidung spätestens bis 2016 sehr früh getroffen
- Nicht nur Datenbanken haben Schwierigkeiten auf S3
- Viele Dateiformate setzen günstige
seek-Operationen voraus - Zip-Dateien sind ein typisches Beispiel dafür, dass sie auf Festplatte besser performen als auf S3
- Viele Dateiformate setzen günstige
Was an S3 enttäuscht
- Die S3-API ist nur XML
- JSON existierte zwar schon 2006, aber damals dominierte XML
- Schade ist, dass Amazon beim Wechsel von SOAP zu REST keine JSON-Version herausgebracht hat
- Amazon pflegt auch das XSD-Schema nicht mehr
- Einer der Hauptvorteile einer XML-API ist gerade das Schema, doch heute ist das Standarddokument die Website
- Amazon stellt keine lokale Testumgebung bereit
- In Python wird für ernsthafte Tests oft die Bibliothek moto verwendet
- Obwohl moto ein Testwerkzeug für einen kommerziellen Dienst ist, wird es von Freiwilligen gepflegt
- Amazon S3 unterstützt Checksummen, aber sie sind standardmäßig nicht aktiviert
- Amazon macht verschiedene Aussagen zur Haltbarkeit
- Von realen Problemen habe ich zwar nichts gehört, aber auch keine Fälle gesehen, in denen diese Aussagen getestet wurden
- Früher hatte S3 die Falle der Eventual Consistency
- Wenn man eine Datei las, überschrieb und erneut las, konnte man noch den alten Inhalt sehen
- Das trat gelegentlich für kurze Zeit auf und sorgte für Verwirrung
- Andere S3-Implementierungen haben dieses Verhalten nicht nachgebildet, und Amazon hat es vor einigen Jahren mit strong read-after-write consistency behoben
1 Kommentare
Meinungen auf Hacker News
Die Haltbarkeit von S3 mag übertrieben wirken, ist aber glaubwürdig und lässt sich schwer mit traditionellen Dateisystemen vergleichen
Der Unterschied betrifft nicht nur Software, sondern auch physische Infrastruktur und Sicherheitskultur; die Isolation der Availability Zones von AWS wirkt besser als bei anderen Clouds
Während der Arbeit an S3 wurde man oft mit Preisvergleichen zu GCP Blob Storage konfrontiert, aber Google konnte Daten im selben Gebäude oder in einem anderen Raum desselben Gebäudes ablegen, daher war das kein fairer Vergleich zur AWS-artigen Trennung
Die gesamte Organisation war extrem auf Datenintegrität fixiert, versah alles mit Prüfsummen und bereitete sich auch auf große Ereignisse wie Naturkatastrophen vor
In der Größenordnung von S3 ließ sich sogar Bit Rot erkennen, etwa zufällige Bitflips, die entstehen, wenn Gammastrahlen auf Festplatten-Platter treffen; zudem wurden Ausfallraten nach Plattenhersteller und Produktionszeitraum gemessen, um die Wahrscheinlichkeit von Datenverlust selbst bei defekten Chargen zu verringern
Man würde wichtige Daten angeblich nirgendwo anders speichern und hat das S3-Placement-System selbst gebaut
Diese Beschreibung klingt, als würde man Cinnabon dafür loben, den Teig selbst herzustellen; die genannten Dinge sind das, was Storage-Unternehmen normalerweise tun
Alles mit Prüfsummen zu versehen ist eine Grundfunktion vieler Dateisysteme, und wenn sogar ein Heimcomputer Bit Rot erkennen und Benachrichtigungen ausgeben kann, dann machen große Storage-Anbieter das selbstverständlich
Auch das Nachverfolgen von Ausfallraten nach Plattenhersteller ist üblich; Storage-Unternehmen veröffentlichen dazu sogar Berichte, und selbst eine IT-Organisation mit sechs Personen hat das per Spreadsheet verwaltet
Auch außerhalb von AWS – und schon lange bevor es AWS gab – haben viele kluge Leute im Storage-Bereich gearbeitet
Georedundante Konten von rsync.net befinden sich zum Beispiel in unterschiedlichen Bundesstaaten oder Ländern, etwa mit Primärspeicher in Fremont und Sekundärspeicher in Denver
Dass S3 wegen seiner Größe Bit Rot erkennen könne, stimmt ebenfalls nicht; auch mit ZFS auf einem privaten Server lässt sich Bit Rot im kleinen Maßstab gut erkennen
[1] he.net-Zentrale
Wenn es genügend solcher Beschädigungsereignisse gibt, könnte das auch als Signal dienen, einzelne Datenblöcke auf andere Maschinen zu verschieben und das System zu „heilen“
Insgesamt sind die genannten Dinge in Storage-Systemen ziemlich typisch und keine Besonderheit von S3
Laut der Dokumentation zu Google Cloud Storage werden Daten über mehrere Zonen repliziert, und jede Zone wird auf unterschiedliche Cluster abgebildet
https://cloud.google.com/compute/docs/regions-zones/zone-vir...
Ich frage mich, ob es eine neutrale Drittpartei gibt, die Haltbarkeit, Integrität und Konsistenz von S3 so streng geprüft hat wie Jepsen
Wenn jemand S3-kompatible Cloud-Storage-Dienste gründlich vergleichen würde, könnten dabei erschreckende große Probleme sichtbar werden; vielleicht gibt es so einen Vergleich auch schon
Was an S3 wirklich nützlich ist, ist meiner Ansicht nach eher das Listing als die Lese-/Schreibgeschwindigkeit
In Buckets ohne Versionierung oder ohne Delete Marker funktioniert das Auflisten eines bestimmten Präfixes praktisch wie in konstanter Zeit, sodass man selbst in einem Bucket mit 100 Milliarden Objekten die 1000 alphabetisch folgenden Keys nach einer beliebigen Zeichenkette anfordern kann
/als Trennzeichen zu verwenden ist nur der Standard; man kann jedes beliebige Zeichen nutzen, um eine Menge gemeinsamer Präfixe zu erhalten, und Verzeichnisse existieren nicht wirklich, sondern sehen nur so aus, als würden sie bei Bedarf erzeugtDank dieser Eigenschaft kann man Daten ohne Performance-Sorgen auf verschiedene Arten nach den benötigten Identifikatoren aufteilen
Wenn Listing einfach langsam wäre, dateipräfixbasierte Abfragen nicht möglich wären und es wie bei einem traditionellen Unix-Dateisystem proportional zur Anzahl der Keys langsamer würde, wäre S3 überhaupt nicht nützlich
Die Fähigkeit, Keys vor und nach einem Präfix herauszuziehen, ist eine Grundfunktion von Datenbankindizes, die es seit den 1970er-Jahren gibt, und daher nicht besonders beeindruckend
Die Anwendungsfälle mögen unterschiedlich sein, aber langsames Bucket-Listing war oft hinderlich; sobald ein Bucket auch nur etwas größer wurde, dauerte das Auflisten der Keys länger als das Lesen
Meiner Erinnerung nach lag das Listing unter 1 Mbit/s, aber ich habe gerade keinen großen Bucket zum Testen
Wenn es
dir1/a/000000bisdir1/a/999999sowiedir1/bgibt, mussls dir1/in einem echten hierarchischen Dateisystem nur die zwei Einträge"a"und"b"durchlaufen und zurückgebenEin flacher String-Index-Key-Value-Store ohne Trennzeichenbehandlung muss dagegen eine Million Verzeichniseinträge von
"a/00000"bis"a/999999"durchlaufen, bevor er"b"erreichtDeshalb wird bei einer einfachen flachen Hierarchie das Auflisten eines Verzeichnisinhalts nicht zu
O(direkte Kinder)wie in einem echten Dateisystem, sondern zuO(alle rekursiven Kinder)und ist damit viel langsamerWenn man dem Listing-Algorithmus jedoch ein Trennzeichen wie
/mitteilt, kann der lexikografische Präfixbaum effizient am nächsten/ganze Teilbäume überspringenAuch die Amazon-S3-Dokumentation sagt ausdrücklich, dass das Feld
CommonPrefixesMillionen von auf tieferen Ebenen verschachtelten Keys überspringt und zusammenfassthttps://docs.aws.amazon.com/AmazonS3/latest/userguide/using-...
Ob die tatsächliche Implementierung wirklich die Traversierung einspart oder nur nach der Traversierung die Ergebnisse reduziert, habe ich nicht getestet, aber ich hoffe, dass sie sie einspart
Daher werden sie nicht proportional zur Anzahl der Einträge langsamer, und auch dateipräfixbasierte Listings sind sehr schnell
Präfix-Listing als Kernfunktion zu sehen, wirkt seltsam
Dass man mit einem Netzwerkaufruf 1000 Keys bekommt, garantiert nichts über die Komplexität im Backend
Kürzlich habe ich an einem Skript zur Verwaltung von S3-Assets gearbeitet und war von der Geschwindigkeit der Listenabfrage überrascht.
Ein Kollege meinte, wir bräuchten einen Cache für die Dateiliste, und schickte mir einen vorbefüllten Cache. Zuerst dachte ich, dass das unmöglich nötig sein könne, aber als ich es selbst prüfte, sah die Sache anders aus.
Es gibt etwa 100.000 Root-Verzeichnisse für einzelne Assets, jeweils mit 5 bis 6 Verzeichnissen und einigen wenigen Dateien; insgesamt sind es vermutlich unter 1 Million Dateien, mit einer Tiefe von höchstens etwa 3 Ebenen.
Diese Dateien rekursiv aufzulisten dauerte buchstäblich 15 Minuten.
Ich habe verschiedene Vorschläge zur Beschleunigung von Stack Overflow und ChatGPT ausprobiert, aber ohne nennenswertes Ergebnis, und verstehe nicht, warum es so langsam ist.
Ich weiß nicht, warum Amazon das nicht behoben hat; von außen wirkt es so, als müsste man einzelnen Buckets nur ein paar B-Bäume verpassen.
Wenn es ein schwieriges Problem ist, wäre der Grund dafür interessant, und ich würde ihn gern hören.
Dass man Objekte wie „Verzeichnisse“ betrachten kann, ist nur ein Präfixfilter; es ist kein Dateisystem und kennt auch kein Verzeichniskonzept.
Die schnellste Methode, Objekte in S3 aufzulisten, braucht überhaupt keine Rekursion; man listet einfach alle Objekte unter einem Präfix auf.
Wenn man mit Pfadtrennern S3-Keys als Ordnerstruktur tarnt und „ordnerweise“ durchläuft, wird es deutlich langsamer.
Beim Aufruf von
ListObjectsV2sollte man keinendelimiterübergeben; wenn man die Trennzeichen-Funktion nicht nutzt, haben „Verzeichnisse“ und „Ebenen“ keinen Einfluss auf die Performance.Um eine gewünschte Gesamtdauer zu erreichen, kann man eine Listenoperation in parallele Listenabfragen über mehrere Präfixe aufteilen.
Ein Bucket, der Objekte enthält, kann nicht gelöscht werden, und man kann S3 auch nicht in einem Schritt sagen, es solle alle Objekte löschen.
Für jedes Objekt muss eine eigene Delete-API-Anfrage gesendet werden; dafür muss man außerdem Anfragen senden, die die Objekte in 1000er-Schritten auflisten, und diese Listenaufrufe brauchen Zeit und kosten Geld.
Dieser Artikel fasst die Lage gut zusammen: https://cloudcasts.io/article/deleting-an-s3-bucket-costs-mo...
Die schnellste Methode, einen S3-Bucket rasch loszuwerden, ist am Ende, das AWS-Konto zu löschen, zu dem dieser Bucket gehört.
Pro Anfrage kann man 10.000 Objekte auflisten, und um die nächsten 10.000 zu bekommen, braucht man das Ergebnis der vorherigen Anfrage; das Ganze ist also vollständig seriell.
Um 1 Million Dateien aufzulisten, braucht man 100 aufeinanderfolgende Anfragen; selbst bei nur 50 ms Roundtrip-Zeit sind das allein 5 Sekunden für die Roundtrips, und die Kosten für das Erstellen der Liste selbst in einer flachen Iteration kommen noch hinzu.
Eine Listenabfrage über 10.000 Einträge kostet ungefähr so viel wie ein Schreibvorgang, was an sich schon eher langsam ist; außerdem könnte jede Listenabfrage ein Snapshot mit starker Konsistenz sein, was zusätzliche Kosten verursacht.
B-Bäume dürften wenig helfen, außer wenn man tatsächlich Verzeichnisse durchläuft; selbst dann liegt der Engpass wahrscheinlich bei Netzwerkoperationen und der nach außen exponierten API.
Letztlich ist das Auflisten von Dateien kein besonders wichtiger Use Case; normalerweise überlässt man S3 mit Funktionen wie Object Lifecycle die gewünschte Arbeit und lässt sie in der internen Dateisystemschicht effizient erledigen.
Es sind alles Objekte; die Weboberfläche stellt lediglich durch Schrägstriche getrennte Präfixe hübsch dar.
Jedes Objekt hat einen Key, und dieser Key kann Schrägstriche enthalten; der Einfachheit halber kann man die einzelnen Abschnitte als Verzeichnisse betrachten.
Aber sobald man versucht, typische Operationen auf Verzeichnissen auszuführen, zerbricht diese Illusion.
Die Leute, die S3 gebaut haben, wussten, dass es kein Dateisystem ist, und ich denke, der Name Objektspeicher sollte genau die im Artikel angesprochenen Unterschiede ausdrücken.
Wenn es heißt, „Objekte waren beliebt“, meint das Objekte als Softwarekomponenten, die ausführbaren Code und lokalen Zustand bündeln; die frühen Beispiele für S3 bestanden aber nicht darin, „Live-Objekte zu serialisieren und in einem anderen Prozess zu deserialisieren“.
Die Beispiele waren allesamt Dinge wie statische Assets für Websites, und auch im Datenbankbereich wurde damals das Wort Objekt in Begriffen wie „binary large object“ oder „blob“ verwendet.
S3 war eher ein Ort, an dem man Dinge speicherte, die schlecht in eine Datenbank passten; die beim ursprünglichen Design vorgesehenen Launch-Use-Cases gingen davon aus, dass der Content-Index irgendwo anders liegt, und genau das erklärt auch, warum Listenabfragen langsam sind.
https://en.wikipedia.org/wiki/Object_storage
Laut der Erklärung von GCP ist Objektspeicher eine Architektur, bei der unstrukturierte Daten in Objekte aufgeteilt und in einer strukturell flachen Datenumgebung gespeichert werden.
https://cloud.google.com/learn/what-is-object-storage
Entscheidend sind also unstrukturierte Daten, eine flache Organisation sowie Lese- und Schreibvorgänge auf Ebene ganzer Einträge.
S3 ist weder eine Datei noch erst recht ein Dateisystem
Was man von der Datei-Abstraktion erwartet, ist Veränderbarkeit: Man sollte Teile einer Datei bearbeiten, sie vergrößern und verkleinern sowie an beliebigen Offsets lesen und schreiben können.
Hat man eine Datei einmal geöffnet, sollte man nicht wieder zur Wurzel oder zu einem übergeordneten Konzept zurückgehen müssen. S3 bietet jedoch nur unveränderliche Objekte auf einer veränderlichen Liste; will man etwas ändern, muss man es kopieren und erneut hochladen.
Die ursprüngliche Datei-Abstraktion besteht darin, Sektoren auf einer Festplatte zu finden und sie dem Client wie einen zusammenhängenden Puffer erscheinen zu lassen; S3 löst ein anderes Problem.
Viele missverstehen die gute UNIX-Idee „Alles ist eine Datei“ so, als müsse alles wie ein zusammenhängender virtueller Puffer aussehen.
Der eigentliche Kern ist, dass es grundlegende Blattknoten gibt – seien es Dateien oder andere Objekte, die das System einem Prozess zeigen möchte –, dass alles, einschließlich Verzeichnissen, in Verzeichnissen aufgelistet werden kann, und dass es einen rekursiven Baum gibt.
Was ein Dateisystem ausmacht, ist nicht der Typ eines bestimmten Blattknotens, sondern das Verzeichnis.
Neue Blatt-Typen wie Sockets oder Framebuffer hinzuzufügen ist nahezu trivial und beschädigt diese Idee nicht; fügt man jedoch andere Arten von Containern wie Listen hinzu, wird die Dateisystemstruktur komplizierter und die konzeptionelle Konsistenz bricht.
S3 tut all das nicht, aber das ist in Ordnung.
Man legt dort Dinge ab, die nicht in eine Datenbank passen, und hofft lediglich, dass kein Bit Rot entsteht, während man nicht hinsieht.
Der Wunsch, S3 wie ein Dateisystem zu machen, entsteht meiner Ansicht nach daraus, dass Kunden missverstehen, worin S3 gut ist, und das Produktmanagement dieses Missverständnis nicht verhindert, sondern akzeptiert hat.
Die passendere Analogie ist ein Blockspeichergerät, allerdings eher ein sehr merkwürdiges Blockgerät, bei dem die Blockgröße beliebig ist und Schlüssel vergeben werden können.
Ein Dateisystem ist eine Abstraktion, die auf einem Blockspeichergerät aufsetzt; ein „S3-Dateisystem“ müsste also ebenfalls eine Abstraktion sein, die S3 als zugrunde liegenden Blockspeicher verwendet.
Ein Dateisystem ist eine Abstraktion, die auf einem Blockgerät aufgebaut ist.
Ein Blockgerät stellt ein riesiges Byte-Array bereit und ermöglicht blockweises Lesen und Schreiben, etwa: „Schreibe diese 300 Bytes an Position 273041“.
Auch das Blockgerät selbst ist eine Abstraktion über tatsächlicher Hardware; „Schreibe diese 300 Bytes“ führt in Wirklichkeit zu Vorgängen wie „Bewege den Kopf von Platter 2 auf Position 6“.
S3 ist lediglich eine andere Abstraktion auf rohem Speicher und streng genommen ein flacher Key-Object-Store.
Wenn man Dateisystemfunktionen braucht, sollte man sie in der App implementieren oder ein Dateisystem verwenden.
Wenn man nur Anhängen braucht, kann man die Append-Kette in einer Datenbank verfolgen und die Chunks in S3 speichern; passt das nicht, nimmt man etwas anderes.
Wenn man Kopieren braucht, kann man in der Datenbank eine neue Referenz auf dasselbe Objekt anlegen; passt das nicht, nimmt man etwas anderes.
S3 passt für viele sehr gut, daher sollte man nicht versuchen, es in etwas anderes zu verwandeln.
Man sollte auch aufhören, die Bedeutung bereits etablierter Fachbegriffe ändern zu wollen: Ein Dateisystem ist ein in Lehrbüchern beschriebenes Konzept, und S3 hat nie behauptet, ein Dateisystem zu sein.
Ein wenig Betriebssystemdesign zu lernen hilft wirklich und macht auch Spaß.
Eine Diskussion zum Vergleich der APIs von Apache Arrows
object_storeund Apache OpenDAL gab es unter https://github.com/apache/arrow-rs/issues/3888.Apache OpenDAL ist eine Bibliothek, die eine dateisystemähnliche API über mehrere Backends hinweg bereitstellt, darunter S3 und verschiedene Cloud-Speicher.
Einige Datenbanksysteme wie GreptimeDB und Databend verwenden OpenDAL als eine Art besseres S3-SDK für den Zugriff auf Daten in Cloud-Speichern.
Als weitere Lösungen, die eine dateisystemähnliche Schnittstelle über S3 verwalten, gibt es auch Alluxio und JuiceFS; anders als Apache OpenDAL erfordern sie jedoch separate Deployments und einen dedizierten internen Metadaten-Service.
Wenn man über S3 spricht, ist auch Backblaze B2 erwähnenswert.
Es ist dreimal günstiger als S3, was mir sehr gefällt; ich bin nicht mit Backblaze verbunden.
Es gibt jede Woche ein zweistündiges Wartungsfenster von 11:30 bis 13:30 Uhr PST; normalerweise gibt es keine Downtime, aber gelegentlich kommt es mitten während der US-Geschäftszeiten zu einem vollständigen Ausfall.
Wenn die Fehlerrate auf ein unbrauchbares Niveau stieg, musste ich ein Support-Ticket eröffnen; in den letzten Jahren ist das ungefähr einmal pro Jahr passiert.
Der Support stellt nur unzählige Fragen, als hätte er keine Fehlerlogs oder Sichtbarkeit auf der eigenen Seite, und schaut sich das Problem nicht wirklich an.
Es gibt auch False Successes, bei denen ein Upload als erfolgreich beantwortet wird, tatsächlich aber mit 0 Bytes im B2-System gespeichert wird; daher muss man Uploads auch bei Erfolgscodes unbedingt verifizieren.
Bei Schwachstellen mit hohem Schweregrad wie der Log4j2-CVE kann es auch zu langen Ausfällen kommen, etwa 10 Stunden Unterbrechung.
Der Preis ist hervorragend, aber es ist kein Produkt, das direkt mit ausgereifteren Cloud-Speicherdiensten vergleichbar ist.
Allerdings lässt sich das meiner Meinung nach durch zwei Ebenen externer Backups bis zu einem gewissen Grad abfedern.
Es ist absurd, dass ein Dienst sich als Multi-Cloud-Lösung bewirbt, während NAT-Gateways und IPv4-Gebühren praktisch überall anfallen und die Einführung damit faktisch unmöglich machen.
Bei meinem Nutzungsprofil mit vielen Lese- und wenigen Schreibzugriffen hätte ich trotz B2-Bandbreitengebühren Geld sparen können; aber nicht, wenn ich über ein NAT64-Gateway gehen oder stündliche Gebühren zahlen muss, um auf B2 zuzugreifen.
Guter Beitrag; es wäre nützlich gewesen, ihn zu lesen, bevor ich meine Reise begonnen habe, Cloud-Speicher mit rclone mount per FUSE einzubinden.
Nach mehreren Iterationen hat rclone eine VFS-Schicht bekommen, die Speicher wie S3, Google Cloud Storage, Azure Blob, OpenStack Swift oder Oracle Object Storage auf eine POSIX-ähnliche Dateisystemschicht abbildet; der eigentliche
rclone mount-Code ist nur eine dünne Schicht darüber.Die VFS-Schicht hat mehrere Kompatibilitätsstufen; bei
offwird nur das Verzeichnis-Caching gemacht.In diesem Modus kann man, wie im Beitrag beschrieben, dieselbe Datei nicht gleichzeitig lesen und schreiben, nicht in die Mitte einer Datei schreiben, und Dateien können nur sequenziell geschrieben werden.
Erstaunlicherweise funktioniert selbst mit diesen Einschränkungen ziemlich viel gut.
Die nächste Stufe,
writes, unterstützt die meisten POSIX-Funktionen, die Apps erwarten, etwa gleichzeitiges Lesen und Schreiben derselben Datei oder Schreiben in die Mitte einer Datei; das kostet aber, dass eine lokale Kopie der Datei angelegt und beim Schließen asynchron hochgeladen wird.Die Dokumentation zum VFS-Caching-Modus bildet die im Beitrag genannten Einschränkungen gut ab: https://rclone.org/commands/rclone_mount/#vfs-file-caching
Grundsätzlich gibt es in S3 auch keine echten Verzeichnisse, daher kann man keine Verzeichnisse ohne Dateien haben, und Verzeichnisse haben auch keine gültigen Metadaten wie Änderungszeiten.
Man kann Directory Marker anlegen, also 0-Byte-Dateien, die auf
/enden, und viele Tools, darunter rclone, unterstützen das.Dass es keine leeren Verzeichnisse gibt, ist normalerweise kein großes Problem, weil die VFS-Schicht sie vortäuscht und die meisten Apps kurz darauf ohnehin etwas hineinschreiben.
Letztlich ist es ziemlich viel Arbeit, etwas, das wie S3 aussieht, wie ein POSIX-Dateisystem aussehen zu lassen; hinter Verhalten wie dem Umbenennen geöffneter Dateien und kniffligen Sonderfällen steckt viel Täuschung.
Die Low-Level-Befehle
move/sync/copyvon rclone machen diese Behandlung nicht, sondern verwenden die S3-API weitgehend unverändert.Wenn ich eine Sache an der S3-API ändern könnte, hätte ich gern eine Option, bei Listenabfragen auch Metadaten zu lesen.
rclone speichert die Änderungszeit von Dateien in Objektmetadaten, aber es gibt keine Möglichkeit, diese massenhaft zu lesen, sodass für jedes Objekt ein
HEADnötig ist.Alternativ wäre es auch gut, beim Upload das
Last-Modifiedeines Objekts setzen zu können.Die Schlüssellänge ist auf 1024 begrenzt, daher ist die Menge speicherbarer Metadaten begrenzt, aber selbst unter Berücksichtigung des Dateipfads ist das ziemlich großzügig.
Man könnte ein in normalisierten Pfaden ungültiges Trennzeichen wie
//verwenden und etwa/path/to/file.txt//mtime=1710066090ablegen.Man könnte weiterhin das „Verzeichnis“ per Präfix holen und
//wie ein Präfix verwenden, um die Datei direkt zu holen.Allerdings würde so ein Format die Kompatibilität mit anderer Software vermutlich stark beeinträchtigen.
MinIO hat einen „geheimen“ Parameter
metadata=truehinzugefügt, der bei passenden Berechtigungen Metadaten und Tags in Listenabfragen einschließt.Da es eine Erweiterung ist, kann man sich nicht stabil darauf verlassen, aber rclone könnte es immer versuchen und nutzen, wenn es verfügbar ist.
0-Byte-Dateien, die auf
/enden, sind ebenfalls möglich, aber man kann auch die gemeinsamen Präfixe einer Listenabfrage selbst als Verzeichnisse betrachten.Dann haben Verzeichnisse keinen Zustand und können nicht existieren, wenn sich keine Objekte darin befinden – mit entsprechenden Vor- und Nachteilen.
Wenn man beim Upload
Last-Modifiedsetzen könnte, gäbe es weniger clientseitige Einschränkungen; es hat aber auch Vorteile, wenn die Serverzeit maßgeblich ist.Bei clientseitiger Replikation oder Spiegelung müssen dieselben Einschränkungen ebenfalls behandelt werden.
Mein persönlich größter Kritikpunkt ist, dass es kein
HeadObjectVersionsgibt, das Versionsinformationen für ein einzelnes Objekt zurückgibt.ListObjectVersionskann nicht wissen, ob ein gegebenes Präfix ein echtes Präfix oder ein Objektschlüssel ist, und muss daher immer potenziell eine clusterweite Operation sein.AWS hat kürzlich
GetObjectAttributeshinzugefügt, aber die Versionsinformationen, die dort gut hineingepasst hätten, sind nicht enthalten.Das „Simple“ in S3 bedeutet nicht „nicht tief“, sondern dass es die wenigsten Bauteile braucht, um die Anforderungen zu erfüllen.
Wenn man einen verteilten, zentralisierten, replizierten, hochverfügbaren, hochhaltbaren, breitbandigen, latenzarmen, stark konsistenten, synchronen, skalierbaren Objektspeicher plus HTTP-REST-API braucht, dürfte es schwierig sein, ihn einfacher als S3 zu bauen.
AWS S3 hat über lange Zeit viele Funktionen dazubekommen, aber das Grundverhalten ist gleich geblieben.
Nach Ousterhouts 『A Philosophy of Software Design』 bedeutet einfach, nicht kompliziert zu sein, und Rich Hickeys „Simple Made Easy“ geht in dieselbe Richtung.
„Tief“ dagegen bedeutet, mit einer kleinen Schnittstelle intern viele komplexe Funktionen bereitzustellen; für S3 passt dieser Ausdruck daher besser als „einfach“.
Das ist etwas anderes als Einfachheit im Sinne von „an S3 ist nicht viel dran“.
https://www.infoq.com/presentations/Simple-Made-Easy/