Hoppa till innehåll

ULID-generator - Skapa unika sorteringsbara ID:n Online Gratis

Gratis ULID-generatorverktyg skapar unika, sorteringsbara identifierare direkt. Generera kryptografiskt säkra ULID:n för databaser, API:er och distribuerade system online.

ULID-generator

Ange ett värde för att se resultat
Laddningsberäknare...
📚

Dokumentation

Vad är en ULID?

En ULID (Universally Unique Lexicographically Sortable Identifier) är en kod på 26 tecken som används för att märka poster i en databas eller en händelse i ett distribuerat system. Den kombinerar den aktuella tiden med slumpdata, så att en lista med ULID:er som sorteras alfabetiskt också sorteras efter när de skapades. En ULID-generator är ett verktyg som skapar dessa koder.

ULID-struktur

En ULID har två delar, skrivna direkt efter varandra utan avgränsare:

  • Tidsstämpel (10 tecken): antalet millisekunder sedan 1 januari 1970 (Unix-epoken), med upp till 48 bitar.
  • Slumpdata (16 tecken): 80 bitar slumpdata, som läggs till så att två ULID:er som skapas under samma millisekund nästan säkert ändå blir olika.

Båda delarna skrivs med Crockfords Base32-alfabet: siffrorna 0–9 och bokstäverna A–Z, med bokstäverna I, L, O och U borttagna. Dessa fyra bokstäver utelämnas eftersom de kan förväxlas med siffrorna 0 och 1 eller med varandra. Resultatet är en sträng som är kort, lätt att läsa högt och säker att placera direkt i en URL.

Så beräknas en ULID

En ULID-generator skapar en identifierare i tre steg.

  1. Läs av den aktuella tiden i millisekunder sedan Unix-epoken. Det är ett tal på 48 bitar.
  2. Generera 80 bitar slumpdata, normalt från en kryptografiskt säker slumptalsgenerator, vilket ger 10 slumpmässiga byte.
  3. Koda båda delarna separat med Crockfords Base32-alfabet: tidsstämpeln på 48 bitar blir 10 tecken och det slumpmässiga värdet på 80 bitar blir 16 tecken. De två kodade strängarna sammanfogas till den slutliga ULID:en på 26 tecken.

Kodningen fungerar genom att läsa 5 bitar åt gången, eftersom varje Base32-tecken representerar ett av 32 möjliga värden (2^5 = 32). Tio tecken rymmer upp till 50 bitar, vilket räcker för tidsstämpeln på 48 bitar. Sexton tecken rymmer exakt 80 bitar, vilket motsvarar slumpdelen utan något överblivet.

Räkneexempel

Anta att en ULID-generator körs vid tidsstämpeln 1712345678901 (millisekunder sedan epoken) och hämtar de slumpmässiga byten [12, 240, 88, 3, 199, 45, 6, 231, 128, 17].

Steg 1 – koda tidsstämpeln. Dividera 1712345678901 upprepade gånger med 32, ta resten varje gång och läs siffrorna från sista till första (detta är vanlig basomvandling). Det ger strängen på 10 tecken 01HTQW311N.

Steg 2 – koda slumpdelen. Packa de 10 slumpmässiga byten i en ström med 80 bitar och läs sedan av 5 bitar åt gången. Omvandla varje block på 5 bitar till ett Base32-tecken. Det ger strängen på 16 tecken 1KR5G0Y75M3EF00H.

Steg 3 – sammanfoga delarna. Den slutliga ULID:en är:

101HTQW311N 1KR5G0Y75M3EF00H
2

skriven utan mellanslag: 01HTQW311N1KR5G0Y75M3EF00H, totalt 26 tecken.

Använda denna generator

Generatorn körs i webbläsaren. Varje ULID byggs från webbläsarens klocka och 80 nya slumpbitar från webbläsarens kryptografiska slumptalsgenerator, så ingen identifierare skickas till eller hämtas från en server.

  • Antal ULID:er tar emot ett heltal från 1 till 50. Standardvärdet är 1.
  • Generera ULID skapar en ny grupp. Om antalet ändras skapas också en ny grupp.
  • Kopiera vid ett resultat kopierar den aktuella ULID:en. När fler än en visas kopierar Kopiera alla hela listan, med en ULID per rad.
  • Återställ ändrar antalet tillbaka till 1 och genererar en ny ULID.

Under resultaten delar panelen ULID-struktur upp den första ULID:en i gruppen i dess två delar: de första 10 tecknen (tidsstämpeln) och de sista 16 (slumpdelen).

ULID jämfört med UUID

FunktionULIDUUID (version 4)
Längd26 tecken36 tecken (med bindestreck)
Kan sorteras efter skapandetidJaNej
KodningCrockford Base32Hexadecimalt
Innehåller en tidsstämpelJa (48 bitar)Nej
URL-säker utan kodningJaJa

Båda formaten syftar till att skapa identifierare som är unika i olika system utan att en central instans delar ut nummer. Den viktigaste praktiska skillnaden är sorteringen: eftersom en ULID börjar med en tidsstämpel sorteras ULID:er även efter tid när de sorteras som vanlig text. Ett slumpmässigt UUID har inte denna egenskap, eftersom varje del av det är slumpmässig.

Vanliga användningsområden

  • Primärnycklar i databaser: ULID:er gör det möjligt för en databas att indexera nya rader ungefär i den ordning de infogades, vilket många databasmotorer hanterar mer effektivt än helt slumpmässiga nycklar.
  • Distribuerade system: separata servrar kan var och en generera ULID:er oberoende av varandra, utan samordning med en central räknare, och resultaten är ändå nästan säkert unika.
  • Händelseloggar: eftersom ULID:er sorteras efter tid kan en lista med händelse-ID:n även fungera som en ungefärlig tidslinje.
  • API- och filidentifierare: formatet med fast längd på 26 tecken, som är URL-säkert, fungerar utan problem i webbadresser och filnamn.

Relaterade identifierarformat omfattar KSUID, som också kodar en tidsstämpel för sortering, och Snowflake-ID:n, som används av Twitter och andra och kombinerar en tidsstämpel, en maskinidentifierare och en räknare.

Kodexempel

Varje exempel nedan bygger en ULID på samma sätt som ULID-specifikationen beskriver: tidsstämpeln på 48 bitar kodas som 10 Crockford Base32-tecken, 80 slumpbitar kodas som ytterligare 16 tecken och delarna sammanfogas.

JavaScript

1const ENCODING_CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
2
3function encodeULID(time, randomBytes) {
4  // Timestamp: 48 bits -> 10 characters
5  let timestampStr = '';
6  let t = time;
7  for (let i = 0; i < 10; i++) {
8    timestampStr = ENCODING_CHARS[t % 32] + timestampStr;
9    t = Math.floor(t / 32);
10  }
11
12  // Randomness: 80 bits -> 16 characters
13  let result = timestampStr;
14  let bits = 0;
15  let bitCount = 0;
16  for (let i = 0; i < 10; i++) {
17    bits = (bits << 8) | randomBytes[i];
18    bitCount += 8;
19    while (bitCount >= 5) {
20      bitCount -= 5;
21      result += ENCODING_CHARS[(bits >> bitCount) & 0x1f];
22    }
23  }
24  return result;
25}
26
27function generateULID() {
28  const randomBytes = crypto.getRandomValues(new Uint8Array(10));
29  return encodeULID(Date.now(), randomBytes);
30}
31
32console.log(generateULID());
33

Python

1import os
2import time
3
4ENCODING_CHARS = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
5
6def encode_ulid(time_ms, random_bytes):
7    # Timestamp: 48 bits -> 10 characters
8    chars = []
9    t = time_ms
10    for _ in range(10):
11        chars.append(ENCODING_CHARS[t % 32])
12        t //= 32
13    timestamp_part = "".join(reversed(chars))
14
15    # Randomness: 80 bits -> 16 characters
16    bits = 0
17    bit_count = 0
18    random_part = []
19    for byte in random_bytes:
20        bits = (bits << 8) | byte
21        bit_count += 8
22        while bit_count >= 5:
23            bit_count -= 5
24            random_part.append(ENCODING_CHARS[(bits >> bit_count) & 0x1F])
25
26    return timestamp_part + "".join(random_part)
27
28def generate_ulid():
29    return encode_ulid(int(time.time() * 1000), os.urandom(10))
30
31print(generate_ulid())
32

Java

1import java.security.SecureRandom;
2import java.time.Instant;
3
4public class ULIDGenerator {
5    private static final SecureRandom random = new SecureRandom();
6    private static final char[] ENCODING_CHARS =
7        "0123456789ABCDEFGHJKMNPQRSTVWXYZ".toCharArray();
8
9    public static String generateULID() {
10        long timestamp = Instant.now().toEpochMilli();
11        byte[] randomBytes = new byte[10];
12        random.nextBytes(randomBytes);
13
14        // Timestamp: 48 bits -> 10 characters
15        char[] timestampChars = new char[10];
16        long t = timestamp;
17        for (int i = 9; i >= 0; i--) {
18            timestampChars[i] = ENCODING_CHARS[(int) (t % 32)];
19            t /= 32;
20        }
21
22        // Randomness: 80 bits -> 16 characters
23        StringBuilder result = new StringBuilder(new String(timestampChars));
24        long bits = 0;
25        int bitCount = 0;
26        for (byte b : randomBytes) {
27            bits = (bits << 8) | (b & 0xFF);
28            bitCount += 8;
29            while (bitCount >= 5) {
30                bitCount -= 5;
31                result.append(ENCODING_CHARS[(int) ((bits >> bitCount) & 0x1F)]);
32            }
33        }
34        return result.toString();
35    }
36
37    public static void main(String[] args) {
38        System.out.println(generateULID());
39    }
40}
41

Vanliga frågor och svar

Vad används en ULID till? En ULID används som en unik identifierare för en databasrad, en API-resurs eller en loggad händelse när det också är praktiskt att kunna sortera efter skapandetid.

Hur lång är en ULID? En ULID är alltid 26 tecken lång: 10 tecken för tidsstämpeln och 16 för slumpdelen.

Vilken kodning använder en ULID? En ULID använder Crockfords Base32-alfabet, som består av siffrorna 0–9 och bokstäverna A–Z, med I, L, O och U borttagna för att undvika förväxling med andra tecken.

Hur skiljer sig en ULID från ett UUID? En ULID sorteras efter skapandetid och är 26 tecken lång. Ett slumpmässigt UUID (version 4) sorteras inte efter tid och är 36 tecken långt inklusive bindestreck.

Hur sannolik är en kollision mellan två ULID:er? De 80 slumpbitarna gör kollisioner extremt osannolika. Det skulle krävas ungefär 1,3 biljoner ULID:er som genereras under samma millisekund för att nå en 50 % sannolikhet att två matchar.

Kan ULID:er genereras utan internetanslutning? Ja. En ULID behöver bara den lokala klockan och en slumptalsgenerator, så den kan skapas helt offline.

Referenser

  1. "ULID Specification." GitHub, https://github.com/ulid/spec.
  2. "Crockford's Base32 Encoding." http://www.crockford.com/base32.html.