Preskoči na vsebino

ULID Generator - Ustvarjanje edinstvenih razvrstitvenih ID-jev Online Brezplačno

Brezplačno orodje za generiranje ULID-jev ustvarja edinstvene, razvrstitvene identifikatorje trenutno. Generirajte kriptografsko varne ULID-je za podatkovne zbirke, API-je in porazdeljene sisteme na spletu.

Generator ULID

Vnesite vrednost za prikaz rezultatov
Kalkulator nalaganja...
📚

Dokumentacija

Kaj je ULID?

ULID (univerzalno enolični leksikografsko razvrstljivi identifikator) je koda z 26 znaki, ki se uporablja za označevanje zapisov v podatkovni zbirki ali dogodka v porazdeljenem sistemu. Združuje trenutni čas z naključnimi podatki, zato je seznam ULID-ov, razvrščen po abecedi, razvrščen tudi po času, ko je bil posamezni ULID ustvarjen. Generator ULID-ov je orodje, ki ustvarja te kode.

Zgradba ULID-a

ULID ima dva dela, zapisana drugega za drugim brez ločila:

  • Časovni žig (10 znakov): število milisekund od 1. januar 1970 (Unixove epohe), ki zajema do 48 bitov.
  • Naključnost (16 znakov): 80 bitov naključnih podatkov, dodanih zato, da sta tudi dva ULID-a, ustvarjena v isti milisekundi, skoraj zagotovo različna.

Oba dela sta zapisana z abecedo Crockford Base32: s števkami 0–9 in črkami A–Z, razen črk I, L, O in U. Te štiri črke so izpuščene, ker jih je mogoče zamenjati s števkama 0 in 1 ali med seboj. Rezultat je kratko besedilo, ki ga je mogoče preprosto prebrati na glas in ga varno neposredno uporabiti v URL-ju.

Kako izračunati ULID

Generator ULID-a ustvari identifikator v treh korakih.

  1. Prebere trenutni čas v milisekundah od Unixove epohe. To je število z 48 biti.
  2. Ustvari 80 bitov naključnih podatkov, običajno s kriptografsko varnim generatorjem naključnih števil, kar da 10 naključnih bajtov.
  3. Ločeno kodira oba dela z abecedo Crockford Base32: časovni žig z 48 biti postane 10 znakov, naključna vrednost z 80 biti pa 16 znakov. Kodirana niza se združita v končni ULID z 26 znaki.

Kodiranje poteka tako, da se število bere po 5 bitov naenkrat, saj vsak znak Base32 predstavlja eno od 32 možnih vrednosti (2^5 = 32). Deset znakov lahko vsebuje do 50 bitov, kar zadostuje za časovni žig z 48 biti. Šestnajst znakov vsebuje natanko 80 bitov, kar se ujema z delom za naključnost, ne da bi kaj ostalo.

Primer izračuna

Predpostavimo, da generator ULID-a deluje pri časovnem žigu 1712345678901 (milisekunde od epohe) in pridobi naključne bajte [12, 240, 88, 3, 199, 45, 6, 231, 128, 17].

Korak 1 – kodiranje časovnega žiga. 1712345678901 večkrat delimo z 32, pri čemer vsakič vzamemo ostanek in števke preberemo od zadnje proti prvi (to je standardna pretvorba številskega sistema). Tako dobimo niz z 10 znaki 01HTQW311N.

Korak 2 – kodiranje naključnosti. 10 naključnih bajtov združimo v tok 80 bitov, nato pa jih beremo po 5 bitov naenkrat ter vsak blok z 5 biti pretvorimo v znak Base32. Tako dobimo niz s 16 znaki 1KR5G0Y75M3EF00H.

Korak 3 – združitev delov. Končni ULID je:

101HTQW311N 1KR5G0Y75M3EF00H
2

zapisan brez presledka: 01HTQW311N1KR5G0Y75M3EF00H, skupaj 26 znakov.

Uporaba tega generatorja

Generator deluje v brskalniku. Vsak ULID je sestavljen iz ure brskalnika in 80 novih naključnih bitov, pridobljenih iz kriptografskega generatorja naključnih števil v brskalniku, zato se noben identifikator ne pošlje strežniku in se z njega ne pridobi.

  • Število ULID-ov sprejme celo število od 1 do 50. Privzeta vrednost je 1.
  • Ustvari ULID ustvari novo skupino. Tudi sprememba števila ustvari novo skupino.
  • Kopiraj pri rezultatu kopira posamezni ULID. Če je prikazanih več ULID-ov, Kopiraj vse kopira celoten seznam, po en ULID v vsako vrstico.
  • Ponastavi nastavi število nazaj na 1 in ustvari en nov ULID.

Podokno Zgradba ULID-a pod rezultati razdeli prvi ULID v skupini na dva dela: prvih 10 znakov (časovni žig) in zadnjih 16 znakov (naključnost).

ULID v primerjavi z UUID

LastnostULIDUUID (različica 4)
Dolžina26 znakov36 znakov (z vezaji)
Razvrščanje po času nastankaDaNe
KodiranjeCrockford Base32Šestnajstiško
Vsebuje časovni žigDa (48 bitov)Ne
Varno za URL brez ubeževanjaDaDa

Oba zapisa sta namenjena ustvarjanju identifikatorjev, ki so enolični v različnih sistemih, ne da bi osrednja avtoriteta dodeljevala številke. Glavna praktična razlika je razvrščanje: ker se ULID začne s časovnim žigom, razvrščanje ULID-ov kot navadnega besedila pomeni tudi njihovo razvrščanje po času. Naključni UUID te lastnosti nima, saj je vsak njegov del naključen.

Pogoste uporabe

  • Primarni ključi podatkovnih zbirk: ULID-i omogočajo, da podatkovna zbirka nove vrstice indeksira približno v vrstnem redu njihovega vstavljanja, kar številni sistemi podatkovnih zbirk obravnavajo učinkoviteje kot povsem naključne ključe.
  • Porazdeljeni sistemi: ločeni strežniki lahko vsak zase ustvarjajo ULID-e brez usklajevanja z osrednjim števcem, rezultati pa so še vedno skoraj zagotovo enolični.
  • Dnevniki dogodkov: ker se ULID-i razvrščajo po času, lahko seznam identifikatorjev dogodkov služi tudi kot približna časovnica.
  • Identifikatorji API-jev in datotek: zapis s fiksnimi 26 znaki, varen za URL-je, se brez težav uporablja v spletnih naslovih in imenih datotek.

Sorodna zapisa identifikatorjev sta KSUID, ki prav tako kodira časovni žig za razvrščanje, in identifikatorji Snowflake, ki jih uporabljajo Twitter in drugi ter združujejo časovni žig, identifikator naprave in števec.

Primeri kode

Vsak spodnji primer ustvari ULID na način, opisan v specifikaciji ULID: časovni žig z 48 biti kodira v 10 znakov Crockford Base32, 80 bitov naključnosti kodira v dodatnih 16 znakov in ju združi.

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

Pogosta vprašanja

Za kaj se uporablja ULID? ULID se uporablja kot enolični identifikator vrstice v podatkovni zbirki, vira API-ja ali zabeleženega dogodka, kadar je koristno tudi razvrščanje po času nastanka.

Kako dolg je ULID? ULID ima vedno 26 znakov: 10 znakov za časovni žig in 16 znakov za naključni del.

Kakšno kodiranje uporablja ULID? ULID uporablja Crockfordovo abecedo Base32, ki jo sestavljajo števke 0–9 in črke A–Z; črke I, L, O in U so izpuščene, da se prepreči zamenjava z drugimi znaki.

Kako se ULID razlikuje od UUID-ja? ULID se razvršča po času nastanka in ima 26 znakov. Naključni UUID (različica 4) se ne razvršča po času in ima 36 znakov, vključno z vezaji.

Kako verjeten je trk med dvema ULID-oma? 80 bitov naključnosti pomeni, da so trki izjemno malo verjetni. Za 50 % verjetnost, da se katera koli dva ujemata, bi bilo treba v isti milisekundi ustvariti približno 1,3 bilijona ULID-ov.

Ali je mogoče ULID-e ustvariti brez internetne povezave? Da. ULID potrebuje le lokalno uro in generator naključnih števil, zato ga je mogoče ustvariti popolnoma brez internetne povezave.

Viri

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