ULID Generátor - Vytvorte Jedinečné Triediteľné ID Online Zadarmo
Bezplatný generátor ULID nástroj vytvára jedinečné, triediteľné identifikátory okamžite. Generujte kryptograficky bezpečné ULID pre databázy, API a distribuované systémy online.
Generátor ULID
Dokumentácia
Čo je ULID?
ULID (univerzálne jedinečný lexikograficky zoraditeľný identifikátor) je kód s dĺžkou 26 znakov, ktorý sa používa na označenie záznamov v databáze alebo udalosti v distribuovanom systéme. Kombinuje aktuálny čas s náhodnými údajmi, takže zoznam ULID zoradený podľa abecedy bude zároveň zoradený podľa času vytvorenia jednotlivých identifikátorov. Generátor ULID je nástroj, ktorý tieto kódy vytvára.
Štruktúra ULID
ULID má dve časti zapísané za sebou bez oddeľovača:
- Časová pečiatka (10 znakov): počet milisekúnd od 1. januára 1970 (Unixovej epochy), vyjadrený najviac 48 bitmi.
- Náhodnosť (16 znakov): 80 bitov náhodných údajov pridaných preto, aby sa dva ULID vytvorené v tej istej milisekunde takmer určite líšili.
Obe časti používajú abecedu Crockford Base32: číslice 0–9 a písmená A-Z okrem písmen I, L, O a U. Tieto štyri písmená sa vynechávajú, pretože si ich možno pomýliť s číslicami 0 a 1 alebo navzájom. Výsledkom je krátky reťazec, ktorý sa ľahko číta nahlas a možno ho bezpečne vložiť priamo do adresy URL.
Ako vypočítať ULID
Generátor ULID vytvára identifikátor v troch krokoch.
- Prečítajte aktuálny čas v milisekundách od Unixovej epochy. Ide o číslo s veľkosťou 48 bitov.
- Vygenerujte 80 bitov náhodných údajov, zvyčajne pomocou kryptograficky bezpečného generátora náhodných čísel, čo predstavuje 10 náhodných bajtov.
- Samostatne zakódujte obe časti pomocou abecedy Crockford Base32: časová pečiatka s veľkosťou 48 bitov sa prevedie na 10 znakov a náhodná hodnota s veľkosťou 80 bitov na 16 znakov. Dva zakódované reťazce sa spoja a vytvoria výsledný ULID s dĺžkou 26 znakov.
Kódovanie funguje tak, že číslo sa číta po 5 bitoch, pretože každý znak Base32 predstavuje jednu z 32 možných hodnôt (2^5 = 32). Desať znakov môže obsahovať až 50 bitov, čo poskytuje dostatok priestoru pre časovú pečiatku s veľkosťou 48 bitov. Šestnásť znakov obsahuje presne 80 bitov, čo zodpovedá časti s náhodnosťou bez zvyšných bitov.
Príklad s riešením
Predpokladajme, že generátor ULID beží pri časovej pečiatke 1712345678901 (milisekundy od epochy) a načíta náhodné bajty [12, 240, 88, 3, 199, 45, 6, 231, 128, 17].
Krok 1 – zakódovanie časovej pečiatky. Číslo 1712345678901 opakovane delíme číslom 32, pričom zakaždým zaznamenáme zvyšok a číslice čítame od poslednej po prvú (ide o štandardný prevod medzi číselnými sústavami). Výsledkom je reťazec s dĺžkou 10 znakov 01HTQW311N.
Krok 2 – zakódovanie náhodnosti. Zbalíme 10 náhodných bajtov do postupnosti 80 bitov, potom ich čítame po 5 bitoch a každý blok s veľkosťou 5 bitov prevedieme na znak Base32. Výsledkom je reťazec s dĺžkou 16 znakov 1KR5G0Y75M3EF00H.
Krok 3 – spojenie častí. Výsledný ULID je:
101HTQW311N 1KR5G0Y75M3EF00H
2zapísaný bez medzery: 01HTQW311N1KR5G0Y75M3EF00H, spolu 26 znakov.
Používanie tohto generátora
Generátor beží v prehliadači. Každý ULID sa vytvára z hodín prehliadača a 80 nových náhodných bitov získaných z kryptografického generátora náhodných čísel prehliadača, takže sa žiadny identifikátor neodosiela na server ani sa z neho nenačítava.
- Počet ULID prijíma celé číslo od 1 do 50. Predvolená hodnota je 1.
- Generovať ULID vytvorí novú skupinu. Zmenou počtu sa takisto vytvorí nová skupina.
- Tlačidlo Kopírovať pri výsledku skopíruje jeden ULID. Ak sa zobrazí viac ako jeden, tlačidlo Kopírovať všetky skopíruje celý zoznam, jeden ULID na riadok.
- Obnoviť nastaví počet späť na 1 a vygeneruje jeden nový ULID.
Pod výsledkami panel Štruktúra ULID rozdelí prvý ULID v skupine na jeho dve časti: prvých 10 znakov (časová pečiatka) a posledných 16 znakov (náhodnosť).
ULID verzus UUID
| Vlastnosť | ULID | UUID (verzia 4) |
|---|---|---|
| Dĺžka | 26 znakov | 36 znakov (s pomlčkami) |
| Zoraditeľné podľa času vytvorenia | Áno | Nie |
| Kódovanie | Crockford Base32 | Hexadecimálna |
| Obsahuje časovú pečiatku | Áno (48 bitov) | Nie |
| Bezpečné pre URL bez potreby kódovania | Áno | Áno |
Oba formáty sú určené na tvorbu identifikátorov, ktoré sú jedinečné naprieč systémami bez centrálnej autority prideľujúcej čísla. Hlavný praktický rozdiel spočíva v triedení: keďže ULID sa začína časovou pečiatkou, triedenie ULID ako obyčajného textu ich zároveň zoradí podľa času. Náhodný UUID túto vlastnosť nemá, pretože každá jeho časť je náhodná.
Bežné použitia
- Primárne kľúče databázy: ULID umožňujú databáze indexovať nové riadky približne v poradí, v akom boli vložené, čo mnohé databázové stroje spracúvajú efektívnejšie než úplne náhodné kľúče.
- Distribuované systémy: samostatné servery môžu vytvárať ULID nezávisle bez koordinácie s centrálnym čítačom a výsledky sú stále takmer určite jedinečné.
- Záznamy udalostí: keďže ULID sa triedia podľa času, zoznam identifikátorov udalostí môže slúžiť aj ako približná časová os.
- Identifikátory rozhraní API a súborov: formát s pevnou dĺžkou 26 znakov bezpečný pre URL funguje bez problémov vo webových adresách a názvoch súborov.
Medzi súvisiace formáty identifikátorov patria KSUID, ktorý tiež kóduje časovú pečiatku na účely triedenia, a identifikátory Snowflake používané spoločnosťou Twitter a ďalšími, ktoré kombinujú časovú pečiatku, identifikátor stroja a počítadlo.
Príklady kódu
Každý príklad nižšie vytvára ULID rovnakým spôsobom, ako to opisuje špecifikácia ULID: časovú pečiatku s veľkosťou 48 bitov zakóduje ako 10 znakov Crockford Base32, 80 bitov náhodných údajov zakóduje ako ďalších 16 znakov a obe časti spojí.
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());
33Python
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())
32Java
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}
41Najčastejšie otázky
Na čo sa ULID používa? ULID sa používa ako jedinečný identifikátor databázového riadka, prostriedku API alebo zaznamenanej udalosti v prípadoch, keď je užitočné aj triedenie podľa času vytvorenia.
Aká je dĺžka ULID? ULID má vždy dĺžku 26 znakov: 10 znakov pre časovú pečiatku a 16 znakov pre náhodnú časť.
Aké kódovanie používa ULID? ULID používa abecedu Crockford Base32 pozostávajúcu z číslic 0–9 a písmen A-Z, z ktorých sú odstránené I, L, O a U, aby nedochádzalo k zámene s inými znakmi.
Ako sa ULID líši od UUID? ULID sa triedi podľa času vytvorenia a má dĺžku 26 znakov. Náhodný UUID (verzia 4) sa podľa času netriedi a má dĺžku 36 znakov vrátane spojovníkov.
Aká je pravdepodobnosť kolízie medzi dvoma ULID? 80 bitov náhodnosti spôsobuje, že kolízie sú mimoriadne nepravdepodobné. Na dosiahnutie 50 % pravdepodobnosti, že sa dve hodnoty zhodnú, by bolo potrebné vygenerovať približne 1,3 bilióna ULID v rámci tej istej milisekundy.
Dajú sa ULID generovať bez internetového pripojenia? Áno. ULID potrebuje iba miestny čas a generátor náhodných čísel, takže ho možno vytvoriť úplne offline.
Referencie
- "ULID Specification." GitHub, https://github.com/ulid/spec.
- "Crockford's Base32 Encoding." http://www.crockford.com/base32.html.