Wat zijn UUID's en waarom zijn ze nuttig?

0
406
Stokkete/Shutterstock.com

Een Universally Unique Identifier (UUID) is een specifieke vorm van identificatie die voor de meeste praktische doeleinden veilig als uniek kan worden beschouwd. Twee correct gegenereerde UUID's hebben een vrijwel verwaarloosbare kans om identiek te zijn, zelfs als ze door afzonderlijke partijen in twee verschillende omgevingen zijn gemaakt. Dit is de reden waarom UUID's universeel uniek worden genoemd.

In dit artikel zullen we kijken naar de kenmerken van UUID's, hoe hun uniciteit werkt en de scenario's waarin ze de identificatie van bronnen kunnen vereenvoudigen. Hoewel we UUID's zullen benaderen vanuit het algemene perspectief van software die interageert met databaserecords, zijn ze breed toepasbaar op elk gebruik waarbij gedecentraliseerde unieke ID-generatie vereist is.

Wat is eigenlijk een UUID?

Een UUID is gewoon een waarde die je veilig als uniek kunt beschouwen. Het risico op een aanrijding is zo laag dat je er redelijkerwijs voor kunt kiezen om het helemaal te negeren. Mogelijk ziet u naar UUID's verwezen met verschillende termen (GUID, of Globally Unique Identifier, is de voorkeurssemantiek van Microsoft), maar de betekenis en het effect blijven hetzelfde.

Een echte UUID is een unieke identifier die wordt gegenereerd en weergegeven door een gestandaardiseerd formaat. Geldige UUID's worden gedefinieerd door RFC 4122; deze specificatie beschrijft de algoritmen die kunnen worden gebruikt om UUID's te genereren die de uniciteit van alle implementaties behouden, zonder een centrale uitgevende instantie.

De RFC bevat vijf verschillende algoritmen die elk een ander mechanisme gebruiken om een ​​waarde te produceren. Hier is een korte samenvatting van de beschikbare “versies”:

  • Versie 1 – Op tijd gebaseerd– Combineert een tijdstempel, een klokreeks en een waarde die specifiek is voor het genererende apparaat (meestal het MAC-adres) om een ​​uitvoer te produceren die uniek is voor die host op dat moment.
  • Versie 2 – DCE-beveiliging – Deze versie is ontwikkeld als een evolutie van versie 1 voor gebruik met Distributed Computing Environment (DCE). Het wordt niet veel gebruikt.
  • Versie 3 – Op naam gebaseerd (MD5)– MD5 hasht een “naamruimte” en een “naam” om een ​​waarde te creëren die uniek is voor die naam binnen de naamruimte. Het genereren van een andere UUID met dezelfde naamruimte en naam zal identieke uitvoer produceren, dus deze methode levert reproduceerbare resultaten op.
  • Versie 4 – Willekeurig – De meeste moderne systemen hebben de neiging om voor UUID v4 te kiezen, omdat het de bron van willekeurige of pseudo-willekeurige getallen van de host gebruikt om de waarden uit te geven. De kans dat dezelfde UUID twee keer wordt geproduceerd, is vrijwel verwaarloosbaar.
  • Versie 5 – Op naam gebaseerd (SHA-1)– Dit is vergelijkbaar met versie 3, maar het gebruikt het sterkere SHA-1-algoritme om de ingevoerde naamruimte en naam te hashen.

Advertentie

Hoewel de RFC naar de algoritmen verwijst als versies, doet dat dat wel niet dat je altijd versie 5 moet gebruiken omdat het schijnbaar de nieuwste is. Welke u moet kiezen, hangt af van uw gebruiksscenario; in veel scenario's wordt v4 gekozen vanwege het willekeurige karakter. Dit maakt het de ideale kandidaat voor het simpele 'geef me een nieuwe identifier'. scenario's.

Generatiealgoritmen zenden een 128-bits geheel getal uit zonder teken. UUID's worden echter vaker gezien als hexadecimale tekenreeksen en kunnen ook worden opgeslagen als een binaire reeks van 16 tekens. Hier is een voorbeeld van een UUID-tekenreeks:

16763be4-6022-406e-a950-fcd5018633ca

De waarde wordt weergegeven als vijf groepen alfanumerieke tekens, gescheiden door streepjes. De streepjes zijn geen verplicht onderdeel van de tekenreeks; hun aanwezigheid is te danken aan historische details van de UUID-specificatie. Ze maken de identificatie ook veel gemakkelijker voor menselijke ogen om waar te nemen.

UUID-use-cases

De belangrijkste use-case voor UUID's is het gedecentraliseerd genereren van unieke identificatiemiddelen. U kunt de UUID overal genereren en veilig als uniek beschouwen, of deze nu afkomstig is van uw backend-code, een clientapparaat of uw database-engine.

UUID's vereenvoudigen het bepalen en onderhouden van de objectidentiteit in niet-verbonden omgevingen. Historisch gezien gebruikten de meeste toepassingen een automatisch oplopend geheeltallig veld als primaire sleutel. Wanneer u een nieuw object maakt, kon u zijn ID pas weten nadat het in de database was ingevoegd. Met UUID's kunt u veel eerder in uw toepassing de identiteit bepalen.

Hier is een eenvoudige PHP-demo die het verschil laat zien. Laten we eerst kijken naar het op integers gebaseerde systeem:

klasse BlogPost { publieke functie __construct( openbare alleen-lezen ?int $Id, openbare alleen-lezen tekenreeks $Headline, openbare alleen-lezen ?AuthorCollection $Authors=null) {} }   #[POST("/posts")] functie createBlogPost(HttpRequest $Request) : ongeldig { $headline = $Request -> getField("Headline"); $blogPost = nieuwe BlogPost(null, $headline); } Advertentie

We moeten de eigenschap $Id initialiseren met null omdat we de werkelijke ID pas kunnen weten nadat deze in de database is bewaard. Dit is niet ideaal – $Id zou niet echt nullable moeten zijn en het zorgt ervoor dat BlogPost-instanties in een onvolledige staat kunnen bestaan.

Overschakelen naar UUID's lost het probleem op:

klasse BlogPost { publieke functie __construct( openbare alleen-lezen tekenreeks $Uuid, openbare alleen-lezen tekenreeks $Headline, openbare alleen-lezen ?AuthorCollection $Authors=null) {} }   #[POST("/posts")] functie createBlogPost(HttpRequest $Request) : ongeldig { $headline = $Request -> getField("Headline"); $blogPost = nieuwe BlogPost("16763be4-…", $headline); }

Post-ID's kunnen nu binnen de applicatie worden gegenereerd zonder het risico van dubbele waarden. Dit zorgt ervoor dat objectinstanties altijd een geldige status vertegenwoordigen en geen onhandige nullable ID-eigenschappen nodig hebben. Het model maakt het ook gemakkelijker om met transactielogica om te gaan; onderliggende records die een verwijzing naar hun ouder nodig hebben (zoals de auteursassociaties van onze berichten) kunnen onmiddellijk worden ingevoegd, zonder een database-retour om de ID op te halen die de ouder is toegewezen.

In de toekomst kan uw blogtoepassing meer logica naar de client verplaatsen. Misschien krijgt de frontend ondersteuning voor het volledig offline maken van concepten, waardoor in feite BlogPost-instanties worden gemaakt die tijdelijk worden bewaard op het apparaat van de gebruiker. Nu kan de client de UUID van de post genereren en deze naar de server verzenden wanneer de netwerkverbinding weer is hersteld. Als de client vervolgens de kopie van het concept van de server heeft opgehaald, kan deze overeenkomen met een eventuele resterende lokale status, aangezien de UUID al bekend zou zijn.

UUID's helpen u ook gegevens uit verschillende bronnen te combineren . Het samenvoegen van databasetabellen en caches die integer-sleutels gebruiken, kan vervelend en foutgevoelig zijn. UUID's bieden uniciteit, niet alleen binnen tabellen, maar op het niveau van het hele universum. Dit maakt ze veel betere kandidaten voor gerepliceerde structuren en gegevens die vaak tussen verschillende opslagsystemen worden verplaatst.

Waarschuwingen wanneer UUID's databases ontmoeten

h2>

De voordelen van UUID's zijn behoorlijk overtuigend. Er zijn echter verschillende problemen waar u op moet letten wanneer u ze in echte systemen gebruikt. Een grote factor in het voordeel van integer-ID's is dat ze eenvoudig te schalen en te optimaliseren zijn. Database-engines kunnen gemakkelijk een lijst met getallen indexeren, sorteren en filteren die maar in één richting gaan.

Hetzelfde kan niet gezegd worden voor UUID's. Om te beginnen zijn UUID's vier keer groter dan gehele getallen (36 bytes versus 4 bytes); voor grote datasets kan dit op zich al een belangrijke overweging zijn. De waarden zijn ook veel lastiger te sorteren en te indexeren, vooral in het geval van de meest voorkomende willekeurige UUID's. Hun willekeurige aard betekent dat ze geen natuurlijke volgorde hebben. Dit is nadelig voor de indexeringsprestaties als u een UUID als primaire sleutel gebruikt.

Advertentie

Deze problemen kunnen zich verergeren in een goed genormaliseerde database die veel gebruik maakt van externe sleutels. Nu heb je misschien veel relationele tabellen, elk met verwijzingen naar je 36-byte UUID's. Uiteindelijk kan het extra geheugen dat nodig is om samenvoegingen en sorteringen uit te voeren een aanzienlijke invloed hebben op de prestaties van uw systeem.

U kunt de problemen gedeeltelijk verminderen door uw UUID's als binaire gegevens op te slaan. Dat betekent een BINARY (16) kolom in plaats van VARCHAR(36). Sommige databases, zoals PostgreSQL, bevatten een ingebouwd UUID-gegevenstype; anderen, zoals MySQL, hebben functies die een UUID-string kunnen converteren naar zijn binaire representatie, en vice versa. Deze aanpak is efficiënter, maar onthoud dat u nog steeds extra middelen zult gebruiken om uw gegevens op te slaan en te selecteren.

Een effectieve strategie kan zijn om gehele getallen als uw primaire sleutels te behouden, maar een extra UUID-veld toe te voegen voor de referentie van uw toepassing. Relationele linktabellen kunnen ID's gebruiken om de prestaties te verbeteren, terwijl uw code objecten op het hoogste niveau met UUID's ophaalt en invoegt. Het komt allemaal neer op uw systeem, de schaal en uw prioriteiten: wanneer u gedecentraliseerde ID-generatie en ongecompliceerde gegevenssamenvoegingen nodig heeft, zijn UUID's de beste optie, maar u moet de afwegingen herkennen.

Samenvatting

UUID's zijn unieke waarden die u veilig kunt gebruiken voor gedecentraliseerde identiteitsgeneratie. Aanrijdingen zijn mogelijk, maar moeten zo zeldzaam zijn dat ze buiten beschouwing kunnen worden gelaten. Als je een hele eeuw lang één miljard UUID's per seconde zou genereren, zou de kans op een duplicaat ongeveer 50% zijn, aangenomen dat er voldoende entropie beschikbaar was.

U kunt UUID's gebruiken om de identiteit onafhankelijk van uw database vast te stellen, voordat er een invoeging plaatsvindt. Dit vereenvoudigt code op applicatieniveau en voorkomt dat onjuist geïdentificeerde objecten in uw systeem voorkomen. UUID's helpen ook bij gegevensreplicatie door uniciteit te garanderen, ongeacht de gegevensopslag, het apparaat of de omgeving, in tegenstelling tot traditionele integer-sleutels die op tabelniveau werken.

Hoewel UUID's nu alomtegenwoordig zijn in softwareontwikkeling, zijn ze geen perfecte oplossing. Nieuwkomers hebben de neiging zich te fixeren op de mogelijkheid van botsingen, maar dit zou niet je eerste overweging moeten zijn, tenzij je systeem zo gevoelig is dat uniekheid moet worden gegarandeerd.

Advertentie

De meest voor de hand liggende uitdaging voor de meeste ontwikkelaars betreft de opslag en ophalen van gegenereerde UUID's. Het naïef gebruiken van een VARCHAR(36) (of het verwijderen van de koppeltekens en het gebruik van VARCHAR(32)) kan uw toepassing in de loop van de tijd verlammen, aangezien de meeste optimalisaties voor database-indexering ineffectief zullen zijn. Onderzoek de ingebouwde UUID-verwerkingsmogelijkheden van uw databasesysteem om ervoor te zorgen dat u de best mogelijke prestaties uit uw oplossing haalt.