Χρειάζεστε ένα αναγνωριστικό που δεν πρόκειται να συγκρουστεί με κάποιο που έφτιαξε κάποιος άλλος, σε ένα μηχάνημα που δεν έχετε ακούσει ποτέ, χωρίς να ζητήσετε άδεια από κανέναν; Αυτή ακριβώς είναι η δουλειά ενός UUID. Είναι ένας αριθμός 128-bit, γραμμένος ως 36 χαρακτήρες στο γνώριμο μοτίβο 8-4-4-4-12, και ολόκληρος ο σχεδιασμός του βασίζεται στο ότι δύο από αυτά δεν πρόκειται να είναι ίδια, παρόλο που τίποτα δεν συντονίζει ποιος παίρνει ποιο. Αυτή η δωρεάν γεννήτρια τα δημιουργεί στον browser σας: επιλέξτε μια έκδοση στο πεδίο Έκδοση, δηλώστε πόσα χρειάζεστε στο πεδίο Πλήθος, και πατήστε Δημιουργία. Η σελίδα ανοίγει με ένα μονό v4, την έκδοση που ζητούν τα περισσότερα έργα, ώστε το πρώτο αναγνωριστικό να απέχει μόνο ένα κλικ.
Κάθε αναγνωριστικό δημιουργείται από τον browser σας μέσω του Web Crypto API. Η έκδοση 4 χρησιμοποιεί την crypto.randomUUID() όπου την παρέχει ο browser, και διαφορετικά την crypto.getRandomValues() — μια κρυπτογραφικά ισχυρή πηγή τυχαιότητας αντί για μια ψευδοτυχαία συνάρτηση JavaScript όπως η Math.random(). Η έκδοση 7 τοποθετεί μια χρονοσφραγίδα 48-bit σε χιλιοστά του δευτερολέπτου στην αρχή, στη συνέχεια έναν μετρητή 12-bit που αυξάνεται μέσα στο ίδιο χιλιοστό του δευτερολέπτου, και έπειτα 62 τυχαία bit, που είναι η μέθοδος ταξινόμησης που περιγράφεται στο RFC 9562· αυτός ο μετρητής είναι ο λόγος που μια παρτίδα χιλίων βγαίνει με τη σωστή σειρά αντί για ανακατεμένη. Η έκδοση 1 συνδυάζει μια χρονοσφραγίδα με ένα τυχαίο αναγνωριστικό κόμβου που έχει ενεργοποιημένο το bit multicast, οπότε δεν φέρει ποτέ τη διεύθυνση της κάρτας δικτύου σας με τον τρόπο που το έκαναν οι αρχικές υλοποιήσεις της δεκαετίας του 1990. Οι εκδόσεις 3 και 5 δεν είναι καθόλου τυχαίες: κατακερματίζουν (hash) έναν χώρο ονομάτων μαζί με ένα όνομα, χρησιμοποιώντας MD5 και SHA-1 αντίστοιχα, και αυτός ο κατακερματισμός συμβαίνει επίσης στη συσκευή σας. Τίποτα δεν αποστέλλεται σε διακομιστή, τίποτα δεν καταγράφεται, και μόλις φορτώσει η σελίδα συνεχίζει να λειτουργεί με τη σύνδεση κλειστή.
Το πεδίο Έκδοση είναι αυτό που αποφασίζει για όλα τα υπόλοιπα. Η έκδοση 4 έχει 122 τυχαία bit και καμία δομή — η προεπιλογή, και η σωστή απάντηση όταν ένα αναγνωριστικό πρέπει απλώς να είναι μοναδικό. Η έκδοση 7 διατηρεί 62 τυχαία bit αλλά ξεκινά με την ώρα που δημιουργήθηκε, ώστε ένα σύνολο από αυτά να ταξινομείται με τη σειρά που φτιάχτηκαν· αυτό την κάνει την έκδοση που πρέπει να επιλέξετε όταν το αναγνωριστικό πρόκειται να γίνει κλειδί σε βάση δεδομένων. Η έκδοση 1 είναι το αρχικό σχήμα που βασίζεται στον χρόνο, και διατηρείται εδώ για συστήματα που εξακολουθούν να τη ζητούν. Οι εκδόσεις 3 και 5 είναι το παράξενο ζευγάρι: είναι ντετερμινιστικές, που σημαίνει ότι οι ίδιες εισαγωγές παράγουν πάντα το ίδιο αναγνωριστικό, και παίρνουν δύο επιπλέον πεδία — τον Χώρο ονομάτων, που είναι ένας από τους τυπικούς χώρους DNS, URL, OID και X.500 ή ένας δικός σας Προσαρμοσμένος χώρος ονομάτων (UUID), και το Όνομα, τη συμβολοσειρά που προσδιορίζεται. Δώστε στο v5 τον χώρο ονομάτων URL και το https://example.com/a και θα πάρετε το ίδιο UUID σήμερα, αύριο και στο μηχάνημα κάποιου άλλου. Εξαιτίας αυτού, το Πλήθος εξαφανίζεται όταν επιλέγεται το v3 ή το v5: χίλια αντίγραφα μιας ντετερμινιστικής τιμής θα ήταν απλώς χίλια αντίγραφα μιας ντετερμινιστικής τιμής. Για κάθε άλλη έκδοση το Πλήθος κυμαίνεται από 1 έως 1000.
Τέσσερις διακόπτες αλλάζουν τη μορφή της εξόδου χωρίς να αλλάξουν τα 128 bit από κάτω. Τα Κεφαλαία τυπώνουν τα δεκαεξαδικά ψηφία ως κεφαλαιογράμματα, το Χωρίς παύλες δίνει τη συμπαγή μορφή 32 χαρακτήρων που προτιμούν ορισμένες στήλες και ονόματα αρχείων, και τα Άγκιστρα τυλίγουν την τιμή σε { } — τη μορφή που τα Windows και ο κόσμος του .NET ονομάζουν GUID. Στις Σύνθετες επιλογές, το urn:uuid: προσθέτει το πρόθεμα που το κάνει επίσημο URN· απενεργοποιεί τα Άγκιστρα και το Χωρίς παύλες όσο είναι ενεργοποιημένο, επειδή το πρότυπο επιτρέπει ακριβώς μία μορφή URN και αυτή είναι η κανονική με τις παύλες. Η Μορφή αντιγραφής αποφασίζει πώς ενώνεται μια παρτίδα όταν την παίρνετε: ένα ανά γραμμή, χωρισμένα με κόμμα, ή κάθε τιμή σε εισαγωγικά με ένα τελικό κόμμα, το οποίο επικολλάται απευθείας σε έναν πίνακα στον κώδικα. Κάτω από το αποτέλεσμα βρίσκεται μια γραμμή που αναφέρει την τυχαιότητα σε bit — 122 για το v4, 62 για το v7 — και, για το v7, τη χρονοσφραγίδα που κωδικοποιείται στο πρώτο αναγνωριστικό της παρτίδας, ώστε ο χρόνος μέσα στην τιμή να είναι ορατός αντί να υπονοείται. Το Αντιγραφή όλων και το Αποθήκευση σε αρχείο σέβονται και τα δύο τη Μορφή αντιγραφής. Το Ιστορικό διατηρεί τις τελευταίες 10 παρτίδες σας στον δικό σας browser: κάντε κλικ σε μία για να την επαναφέρετε, αντιγράψτε ή διαγράψτε μια μεμονωμένη καταχώρηση, ή καθαρίστε τα πάντα. Ο Καθαρισμός αδειάζει το αποτέλεσμα και αφήνει τις ρυθμίσεις σας ανέπαφες, και μετά τα 50 αναγνωριστικά η λίστα γίνεται ένα ενιαίο μπλοκ κύλισης αντί για πενήντα γραμμές.
Το πιο σημαντικό πράγμα σε αυτή τη σελίδα είναι η διαφορά μεταξύ του v4 και του v7 ως πρωτεύον κλειδί (primary key), και δεν είναι θέμα γούστου. Τα ευρετήρια των βάσεων δεδομένων είναι δέντρα (B-tree) που διατηρούνται σε ταξινομημένη σειρά, και το πού προσγειώνεται ένα νέο κλειδί σε αυτή τη σειρά αποφασίζει πόση δουλειά κοστίζει η εισαγωγή. Ένα κλειδί v4 είναι τυχαίο, επομένως διαδοχικές εισαγωγές προσγειώνονται σε άσχετες γωνίες του ευρετηρίου: σελίδες που ήταν γεμάτες διασπώνται (page split), τα μέρη του δέντρου που κρατά η βάση δεδομένων στη μνήμη είναι σπάνια τα μέρη που χρειάζεται η επόμενη εισαγωγή, και το ευρετήριο καταλήγει μεγαλύτερο και πιο κατακερματισμένο από όσο δικαιολογούν οι γραμμές στις οποίες δείχνει. Ένα κλειδί v7 ξεκινά με το τρέχον χιλιοστό του δευτερολέπτου, επομένως διαδοχικές εισαγωγές προσγειώνονται η μία δίπλα στην άλλη στη δεξιά άκρη του δέντρου, το οποίο είναι το μοτίβο που παράγει ένας ακέραιος αριθμός αυτόματης αύξησης και το μοτίβο γύρω από το οποίο χτίστηκαν οι δομές των ευρετηρίων. Αυτός είναι ολόκληρος ο συμβιβασμός: το v7 σας αγοράζει τη συμπεριφορά εισαγωγής ενός διαδοχικού κλειδιού, διατηρώντας παράλληλα την ιδιότητα που σας έκανε να επιλέξετε τα UUID εξ αρχής, η οποία είναι ότι ο καθένας μπορεί να κόψει ένα χωρίς να ρωτήσει έναν διακομιστή. Αυτό που κοστίζει είναι ότι ο χρόνος δημιουργίας είναι πλέον αναγνώσιμος μέσα στο αναγνωριστικό, και το αν αυτό έχει σημασία είναι ένα ερώτημα σχετικά με τα δεδομένα σας, όχι με τη μορφή.
Τίποτα δεν ελέγχει ποτέ ένα UUID για μοναδικότητα· το μέγεθός του είναι η εγγύηση. Δεν υπάρχει κανένα μητρώο, κανένα πήγαινε-έλα σε διακομιστή, καμία αναζήτηση — μια γεννήτρια παράγει έναν αριθμό και τον παραδίδει, και ο λόγος που δύο από αυτούς δεν συγκρούονται είναι απλώς ότι υπάρχουν 2^122 πιθανές τιμές v4, περίπου 5,3 ενδεκάκις εκατομμύρια. Το πρόβλημα των γενεθλίων (birthday problem) είναι ο ειλικρινής τρόπος να μετρηθεί αυτό: θα χρειαζόσασταν περίπου 2,7 πεντάκις εκατομμύρια αναγνωριστικά προτού υπάρξει 50% πιθανότητα να ταιριάξουν οποιαδήποτε δύο από αυτά, που αντιστοιχεί σε ένα δισεκατομμύριο νέα UUID κάθε δευτερόλεπτο για 86 χρόνια. Αξίζει να είμαστε ακριβείς σχετικά με το τι υπόσχεται και τι όχι αυτό. Πρόκειται για μια στατιστική εγγύηση, όχι μια αριθμητική, και ισχύει μόνο όσο η τυχαιότητα από κάτω είναι πραγματική — μια γεννήτρια που αρχικοποιήθηκε άσχημα, ή μια εικονική μηχανή που κλωνοποιήθηκε μαζί με τη δεξαμενή εντροπίας της, τη σπάει με τρόπο που η μορφή δεν μπορεί να εντοπίσει. Η έκδοση 7 περιορίζει το ερώτημα περαιτέρω: μέσα σε ένα μόνο χιλιοστό του δευτερολέπτου μια γεννήτρια δεν μπορεί να επαναλάβει τον εαυτό της καθόλου, επειδή ο μετρητής αυξάνεται αντί να ρίχνει ζάρια, και σε ανεξάρτητες γεννήτριες τα 62 τυχαία bit κάνουν τη δουλειά.
Ένα UUID είναι αναγνωριστικό, όχι κωδικός πρόσβασης. Η έκδοση 4 είναι απρόβλεπτη, και αυτό βάζει τους ανθρώπους στον πειρασμό να την αντιμετωπίζουν ως μυστικό — ως σύνδεσμο επαναφοράς κωδικού πρόσβασης, ως μη μαντεύσιμο URL, ως διακριτικό συνόδου (session token), ως κλειδί API. Η απρόβλεπτη φύση είναι πραγματική, αλλά η μυστικότητα είναι ιδιότητα του πώς χειρίζεται κανείς μια τιμή, και τα αναγνωριστικά αντιμετωπίζονται απρόσεκτα εκ σχεδιασμού: βρίσκονται σε URL, τα οποία καταλήγουν στο ιστορικό του browser, στα αρχεία καταγραφής διακομιστών, σε κεφαλίδες referrer και στα εργαλεία αναλυτικών στοιχείων, και επικολλούνται σε μηνύματα συνομιλίας. Οι άλλες εκδόσεις είναι ακόμη χειρότεροι υποψήφιοι. Η έκδοση 1 και η έκδοση 7 κωδικοποιούν και οι δύο τη στιγμή της δημιουργίας, οπότε οποιοσδήποτε έχει μία γνωρίζει χοντρικά πότε φτιάχτηκε και μπορεί να περιορίσει τη γειτονιά όλων των πραγμάτων που φτιάχτηκαν μαζί της. Οι εκδόσεις 3 και 5 είναι ντετερμινιστικές επί τούτου: ένα UUID v5 μιας διεύθυνσης email δεν είναι ένα κατακερματισμένο μυστικό, είναι μια τιμή που οποιοσδήποτε με την ίδια διεύθυνση μπορεί να υπολογίσει σε ένα δευτερόλεπτο. Χρησιμοποιήστε ένα UUID για να ονομάσετε ένα πράγμα. Χρησιμοποιήστε μια γεννήτρια κωδικών πρόσβασης, ή ένα διακριτικό από μια βιβλιοθήκη φτιαγμένη για μυστικά, όταν η τιμή πρέπει να παραμείνει άγνωστη.
Γιατί να επιλέξετε αυτή τη γεννήτρια UUID;
- Δημιουργία μόνο στον browser: τα αναγνωριστικά φτιάχνονται στη συσκευή σας και δεν στέλνονται ποτέ πουθενά
- Τυχαιότητα Web Crypto API: κρυπτογραφικά ασφαλής, όχι η Math.random()
- Πέντε εκδόσεις σε ένα μέρος: v1, v3, v4, v5 και v7, χωρίς να αλλάζετε εργαλεία
- Πραγματικά ταξινομημένο v7: ένας μετρητής μέσα στο χιλιοστό του δευτερολέπτου, όπως περιγράφει το RFC 9562
- Ντετερμινιστικά v3 και v5 με τους τέσσερις τυπικούς χώρους ονομάτων ή τον δικό σας
- Έως 1000 τη φορά, με μια συμπαγή λίστα κύλισης μετά τα πενήντα
- Κάθε κοινή μορφή: με παύλες, γυμνό, κεφαλαία, με άγκιστρα ή ως URN μορφής urn:uuid:
- Αντιγραφή ως γραμμές, με κόμματα ή σε εισαγωγικά για απευθείας επικόλληση σε κώδικα
- Απεριόριστα και δωρεάν: χωρίς εγγραφή, χωρίς όρια χρήσης, τίποτα στους διακομιστές μας
Τα UUID εμφανίζονται οπουδήποτε πρέπει να ονομαστεί κάτι προτού οτιδήποτε μπορέσει να επιβεβαιώσει ότι το όνομα είναι ελεύθερο. Ο κώδικας της εφαρμογής τα κόβει για γραμμές που πρόκειται να εισαγάγει, έτσι ώστε το αντικείμενο να έχει μια ταυτότητα προτού καν φτάσει στη βάση δεδομένων και ένας πελάτης να μπορεί να κάνει αναφορά σε αυτό ενώ η εγγραφή βρίσκεται ακόμα εν πτήσει. Τα κατανεμημένα συστήματα στηρίζονται πάνω τους πιο έντονα: πολλές υπηρεσίες που γράφουν σε έναν πίνακα, ένας offline πελάτης για κινητά που δημιουργεί εγγραφές σε ένα αεροπλάνο, μια ουρά που πρέπει να αναγνωρίσει το μήνυμα που έχει ήδη επεξεργαστεί — κανένα από αυτά δεν μπορεί να περιμένει τη σειρά του για έναν κοινόχρηστο μετρητή. Η έκδοση 5 καλύπτει μια διαφορετική ανάγκη, η οποία είναι ένα σταθερό αναγνωριστικό που προέρχεται από κάτι που έχετε ήδη: το ίδιο έγγραφο, το ίδιο URL ή ο ίδιος λογαριασμός αντιστοιχίζεται πάντα στο ίδιο UUID, επομένως μια εισαγωγή (import) μπορεί να εκτελεστεί δύο φορές χωρίς να διπλοεγγραφεί τίποτα. Αλλού, είναι απλώς η μορφή που απαιτεί ένα σύστημα — ένα ψηφιακό σύστημα εξυπηρέτησης του Δημοσίου, μια τράπεζα που ενοποιεί δεδομένα πελατών, ένας κόμβος τηλεπικοινωνιών, ή μια ερευνητική ομάδα που συγκεντρώνει μετρήσεις σε ένα bucket· όλα αυτά βασίζονται στη μοναδικότητα που προσφέρουν.
Αξίζει να γνωρίζετε μερικά ειλικρινή όρια. Μια παρτίδα είναι μια έκδοση: η τιμή στο πεδίο Έκδοση ισχύει για όλα όσα περιλαμβάνονται, οπότε μια εκτέλεση v4 και μια εκτέλεση v7 είναι δύο διαφορετικές παρτίδες. Αυτή είναι μια γεννήτρια, όχι ένας επιθεωρητής — η επικόλληση ενός UUID για να διαβαστεί η έκδοσή του ή η χρονοσφραγίδα του δεν είναι κάτι που κάνει αυτή η σελίδα. Το Αποθήκευση σε αρχείο γράφει ένα αρχείο απλού κειμένου (plain text) αντί για CSV ή JSON. Η έκδοση 7 αποκαλύπτει ανοιχτά πότε δημιουργήθηκε, με ακρίβεια χιλιοστού του δευτερολέπτου, το οποίο είναι ένας πραγματικός συμβιβασμός και όχι ελάττωμα, και η έκδοση 1 διαρρέει τον χρόνο με τον ίδιο τρόπο· αν αυτό είναι πρόβλημα για τα δεδομένα σας, η έκδοση 4 είναι η έκδοση που δεν λέει τίποτα σε κανέναν. Δύο ειδικές τιμές από το πρότυπο δεν είναι εκδόσεις και γι' αυτό δεν είναι επιλογές στο πεδίο Έκδοση, αλλά μπορείτε να τις αντιγράψετε από εδώ: το nil UUID, 00000000-0000-0000-0000-000000000000, και το max UUID, ffffffff-ffff-ffff-ffff-ffffffffffff. Τα πάντα σε αυτήν τη σελίδα ακολουθούν το RFC 9562, την προδιαγραφή που αντικατέστησε το RFC 4122 το 2024, οπότε η έξοδος γίνεται αποδεκτή από οποιαδήποτε βιβλιοθήκη, βάση δεδομένων ή API που χειρίζεται καθόλου UUID. Εντός αυτών των ορίων η εγγύηση είναι ισχυρή: κάθε αναγνωριστικό κατασκευάζεται σύμφωνα με το πρότυπο, από κρυπτογραφικά ασφαλή τυχαιότητα, στο δικό σας μηχάνημα, και κανείς άλλος δεν το βλέπει ποτέ.