ID für Ressourcen: GUID oder fortlaufend?
(twitter.com/dylayed)Wenn es darum geht, eine ID zu erzeugen, die eine bestimmte Ressource eindeutig bezeichnet, werden meines Wissens meist vor allem zwei Methoden verwendet. Die eine ist, auf dem Primary Key einer DB-Tabelle Auto Increment zu setzen und den dabei entstehenden fortlaufenden Ganzzahlwert direkt zu verwenden. Die andere ist, jeweils einen zufälligen 128-Bit-Wert zu erzeugen und zu verwenden: eine GUID (auch UUID genannt).
Die Daten unzähliger Dienste im Web werden zu einem großen Teil von RDBMS verwaltet, und das Auto Increment solcher DBMS ist intern nicht nur stark optimiert, sondern aus Sicht von Entwicklern auch leicht zu verstehen und vorhersehbar. Außerdem lassen sich Daten einfach in der Reihenfolge ihres Eingangs sortieren. Es wird ja lediglich eine Zahl jeweils um 1 erhöht. Allerdings kann diese Methode in bestimmten Fällen Informationen nach außen preisgeben, die aus Sicherheitsgründen besser nicht offengelegt würden (zum Beispiel könnten Wettbewerber wichtige Kennzahlen wie die Nutzerzahl unseres Dienstes leicht abschätzen), und sie kann in verteilten Architekturen problematisch sein.
Die Verwendung von GUIDs hat im Vergleich dazu genau entgegengesetzte Eigenschaften. Da GUIDs praktisch eindeutige 128-Bit-Werte sind, die jeweils ohne weitere Abhängigkeiten erzeugt werden und deren Kollisionswahrscheinlichkeit nahe null liegt, verursachen sie auch in verteilten Architekturen keinerlei Probleme. Außerdem besteht nicht die Gefahr, dass nach außen versehentlich andere bedeutungsvolle Informationen durchsickern. Allerdings kann das Schreiben zufällig erzeugter Werte in ein RDBMS zu Leistungseinbußen führen, und außerdem ist es damit allein nicht möglich, Daten in der Reihenfolge ihres Eingangs zu sortieren. Um diese Schwächen auszugleichen, werden manchmal Verfahren wie Timeflake verwendet, die nicht vollständig zufällig sind, sondern Zeitinformationen enthalten und dadurch eine unvollständige Sequenzialität aufweisen. Ich habe das selbst zwar noch nie verwendet, aber ich habe gehört, dass auch Frameworks wie Laravel auf diese Art arbeiten.
Persönlich bin ich durch meine Arbeit im aktuellen Unternehmen, wo ich Produkte entwickle, die mit Dingen wie Microsoft Office 365 oder der Graph API integriert sind und GUIDs aktiv verwenden, zu der Ansicht gekommen, dass eine konsequente Nutzung von GUIDs durchaus ziemlich sinnvoll sein kann. Letztlich hängt so etwas aber davon ab, wofür es eingesetzt wird und welchem Zweck es dient; was besser ist, kann sich also unterscheiden. Deshalb ist es gut, die Vor- und Nachteile der einzelnen Methoden klar zu kennen. In diesem Zusammenhang möchte ich daher einen Tweet-Thread vorstellen, der das Tagebuch eines Entwicklers eines fiktiven Dienstes dazu enthält. (Koreanisch)
15 Kommentare
Kürzlich kam es bei Shinhan Card zu einem Betrugsfall. In diesem Zusammenhang wurde bestätigt, dass der Kartenanbieter Kreditkartennummern fortlaufend vergibt und dadurch dem Risiko ausgesetzt sein könnte, dass Karten aus dem Ausland missbräuchlich verwendet werden.
Die Nummer nur leicht verändert und schon eine „Zahlung“ … Kreditkarten dem Missbrauch ausgesetzt
Finanzaufsicht erarbeitet Maßnahmen zu den jüngsten Betrugsfällen bei Shinhan Card
Dank eurer Kommentare habe ich auch vieles gelernt, was ich vorher nicht wusste.
Dadurch habe ich zum ersten Mal von Dingen wie Hashids, Nano ID und der von Instagram verwendeten Methode erfahren.
Vermutlich mit einer ähnlichen Motivation wie bei
ulid, aber da es einen vorgeschlagenen Internet-Draft gab, habe ich diese Spezifikation in einem früheren Projekt verwendet.https://github.com/uuid6/uuid6-ietf-draft
Solche auf diese Weise erzeugten ID-Systeme sieht man häufig, aber ich denke, es ist inzwischen an der Zeit, zumindest die UUID-ähnlichen Varianten auf einen Standard zu vereinheitlichen.
Aber der Versuch, einen neuen Standard zu schaffen, der die wild wuchernden Standards in einem einzigen vereinheitlichen soll, bringt am Ende meist nur einen weiteren Wettbewerber auf den Markt hervor. haha
https://xkcd.com/927/
Stimmt, haha. Deshalb schlagen wohl alle neue IDs vor.
Vor Kurzem hatte Gyuwon das geteilt, aber ist das eigentlich nicht eine ziemlich einfache Frage?
https://byterot.blogspot.com/2013/02/…
Ich wünsche mir ebenfalls eine zusätzliche Erklärung dazu, warum es sich um ein „einfaches Problem“ handeln soll.
Inwiefern würden Sie sagen, dass das ein simples Problem ist?
In diesem Artikel heißt es zwar: "With storage nowadays very cheap, this normally is not a problem from the storage point of view.", aber es scheint durchaus Situationen zu geben, in denen man UUIDs je nach Kontext ablehnen muss — etwa wenn diese ID über das Netzwerk übertragen werden muss, im Speicher als Schlüssel dient oder als Schlüssel an vielen Stellen in großen Datenmengen verwendet wird und es deshalb wichtig ist, auch nur ein paar Bytes einzusparen.
Das in diesem Beitrag angesprochene Problem ist der Performanceverlust, der entsteht, wenn ein zufällig erzeugter Wert als Primary Key verwendet wird.
(Falls noch andere Probleme erwähnt wurden und ich sie übersehen habe, sagt mir bitte Bescheid.)
Für dieses Problem gibt es bereits eine Antwort. Es ist dasselbe Problem wie bei der cursorbasierten Paginierung in zeitlicher Reihenfolge, daher haben es die meisten vermutlich schon gelöst.
Ich frage mich auch, inwiefern das ein komplexes Problem ist.
Sie sagten, dass die geschilderte Situation abgelehnt werden sollte, daher scheint es eher ein einfaches Problem zu sein ...
Ist ein komplexes Problem nicht eher eines, bei dem man sich so oder so nicht entscheiden kann?
Da die Bedeutung von „einfaches Problem“ unterschiedlich interpretiert werden kann, habe ich gefragt, in welchem Sinne Sie das verwenden. Ob Sie meinen, dass das Problem an sich nicht schwierig ist, oder ob es daran liegt, dass der Artikel eine klare Antwort (?) liefert und es daher wenig Raum zum Abwägen gibt, und so weiter.
Was Ersteres betrifft, denke ich, wie oben erwähnt, dass es kein einfaches Problem ist, weil es je nach Situation viele Faktoren zu berücksichtigen gibt, etwa wenn eine ID auch außerhalb der Datenbank verwendet werden können muss.
In Python/Django gibt es auch so etwas: https://pypi.org/project/django-hashid-field/1.0.0/
Oh, es gibt also auch die Methode Hashids.
Falls das Salt nach außen dringt, könnte zwar das im obigen Beitrag erwähnte Problem der Offenlegung von Informationen nach außen entstehen, aber ich halte es trotzdem für eine gute Methode.
Es gibt auch ULID. 128 Bit, nach Zeit sortierbar.
https://github.com/ulid/spec
Wenn man sieht, wie viele Dinge sich so ähnlich sehen, denkt man fast, dass die Menschen am Ende doch alle auf ähnliche Ideen kommen …?