Прескочи на садржај

ULID Генератор - Креирајте Јединствене Сортабилне ИД-ове Онлајн Бесплатно

Бесплатни ULID генератор алат омогућава тренутно креирање јединствених, сортабилних идентификатора. Генеришите криптографски сигурне ULID-ове за базе података, АПИ-је и дистрибуиране системе онлајн.

ULID Генератор

Унесите вредност да бисте видели резултате
Kalkulator učitavanja...
📚

Dokumentacija

Шта је ULID?

ULID (универзално јединствени лексикографски сортирани идентификатор) је код од 26 знакова који се користи за означавање записа у бази података или догађаја у дистрибуираном систему. Он комбинује тренутно време са случајним подацима, па се листа ULID-ова сортирана по абецеди на крају поређа према времену њиховог креирања. Генератор ULID-ова је алат који производи ове кодове.

Структура ULID-а

ULID има два дела, записана један за другим без раздвајача:

  • Временска ознака (10 знакова): број милисекунди од 1. јануар 1970. (почетак Unix епохе), који заузима до 48 бита.
  • Случајни део (16 знакова): 80 бита случајних података, додатих тако да се два ULID-а креирана у истој милисекунди готово сигурно разликују.

Оба дела се записују помоћу Крокфордовог Base32 алфабета: цифара 0–9 и слова A–Z, без слова I, L, O и U. Та четири слова су изостављена јер се могу заменити са цифрама 0 и 1 или једно са другим. Резултат је ниска која је кратка, лака за читање наглас и безбедна за директно коришћење у URL-у.

Како се израчунава ULID

Генератор ULID-а гради идентификатор у три корака.

  1. Очитајте тренутно време у милисекундама од почетка Unix епохе. То је број од 48 бита.
  2. Генеришите 80 бита случајних података, обично помоћу криптографски безбедног генератора случајних бројева, што даје 10 случајних бајтова.
  3. Кодирајте оба дела засебно помоћу Крокфордовог Base32 алфабета: временска ознака од 48 бита постаје 10 знакова, а случајна вредност од 80 бита постаје 16 знакова. Два кодирана низа се спајају у коначни ULID од 26 знакова.

Кодирање функционише тако што се број чита у групама од по 5 бита, јер сваки Base32 знак представља једну од 32 могућих вредности (2^5 = 32). Десет знакова може да садржи до 50 бита, што је довољно за временску ознаку од 48 бита. Шеснаест знакова садржи тачно 80 бита, колико има и случајни део, без преосталих битова.

Решен пример

Претпоставимо да генератор ULID-а ради са временском ознаком 1712345678901 (милисекунде од почетка епохе) и добија случајне бајтове [12, 240, 88, 3, 199, 45, 6, 231, 128, 17].

Корак 1 – кодирање временске ознаке. Више пута делите 1712345678901 са 32, сваки пут узимајући остатак и читајући цифре од последње ка првој (ово је стандардна конверзија базе). Тако се добија ниска од 10 знакова 01HTQW311N.

Корак 2 – кодирање случајног дела. Спакујте 10 случајних бајтова у низ од 80 битова, затим читајте по 5 битова и сваку групу од 5 бита претворите у Base32 знак. Тако се добија ниска од 16 знакова 1KR5G0Y75M3EF00H.

Корак 3 – спајање делова. Коначни ULID је:

101HTQW311N 1KR5G0Y75M3EF00H
2

записан без размака: 01HTQW311N1KR5G0Y75M3EF00H, укупно 26 знакова.

Коришћење овог генератора

Генератор ради у прегледачу. Сваки ULID се гради на основу часовника прегледача и 80 нових случајних битова добијених од криптографског генератора случајних бројева у прегледачу, па се ниједан идентификатор не шаље серверу нити се са њега преузима.

  • Број ULID-ова прихвата цео број од 1 до 50. Подразумевана вредност је 1.
  • Генериши ULID производи нову групу. Промена броја такође производи нову групу.
  • Копирај поред резултата копира тај појединачни ULID. Када је приказано више њих, Копирај све копира целу листу, по један ULID у сваком реду.
  • Ресетуј враћа број на 1 и генерише један нови ULID.

Испод резултата, панел „Структура ULID-а“ дели први ULID у групи на његова два дела: првих 10 знакова (временску ознаку) и последњих 16 знакова (случајни део).

ULID у односу на UUID

ОсобинаULIDUUID (верзија 4)
Дужина26 знакова36 знакова (са цртицама)
Може се сортирати према времену креирањаДаНе
КодирањеКрокфордов Base32Хексадекадни
Садржи временску ознакуДа (48 бита)Не
Безбедан за URL без енкодовањаДаДа

Оба формата имају за циљ да производе идентификаторе јединствене у различитим системима, без централног ауторитета који додељује бројеве. Главна практична разлика је сортирање: пошто ULID почиње временском ознаком, сортирање ULID-ова као обичног текста истовремено их сортира и по времену. Случајни UUID нема ово својство, јер је сваки његов део случајан.

Уобичајене примене

  • Примарни кључеви базе података: ULID-ови омогућавају бази података да индексира нове редове приближно редоследом њиховог уметања, што многи системи за управљање базама података обрађују ефикасније него потпуно случајне кључеве.
  • Дистрибуирани системи: одвојени сервери могу независно да генеришу ULID-ове, без усаглашавања са централним бројачем, а резултати су и даље готово сигурно јединствени.
  • Дневници догађаја: пошто се ULID-ови сортирају по времену, листа идентификатора догађаја може да послужи и као оквирна временска линија.
  • Идентификатори API-ја и датотека: фиксни формат од 26 знакова, безбедан за URL, добро функционише у веб адресама и називима датотека.

Сродни формати идентификатора обухватају KSUID, који такође кодира временску ознаку ради сортирања, и Snowflake ID-је, које користе Twitter и други, а који комбинују временску ознаку, идентификатор машине и бројач.

Примери кода

Сваки пример у наставку гради ULID на исти начин као што описује спецификација ULID-а: кодира временску ознаку од 48 бита као 10 Крокфордових Base32 знакова, кодира 80 бита случајности као још 16 знакова и спаја их.

Јаваскрипт

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

Питон

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

Јава

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

Најчешће постављана питања

За шта се користи ULID? ULID се користи као јединствени идентификатор реда у бази података, ресурса API-ја или забележеног догађаја, када је корисно и сортирање према времену креирања.

Колико је дугачак ULID? ULID увек има 26 знакова: 10 знакова за временску ознаку и 16 за случајни део.

Које кодирање користи ULID? ULID користи Крокфордов Base32 алфабет, састављен од цифара 0–9 и слова A–Z, при чему су I, L, O и U уклоњени да би се избегла забуна са другим знаковима.

По чему се ULID разликује од UUID-а? ULID се сортира према времену креирања и има 26 знакова. Случајни UUID (верзија 4) не сортира се према времену и има 36 знакова, укључујући цртице.

Колика је вероватноћа судара између два ULID-а? 80 битова случајности чине сударе изузетно мало вероватним. Било би потребно генерисати приближно 1,3 билиона ULID-ова у истој милисекунди да би се достигла вероватноћа од 50% да се било која два поклопе.

Могу ли се ULID-ови генерисати без интернет везе? Да. ULID-у су потребни само локални часовник и генератор случајних бројева, па се може у потпуности креирати ван мреже.

Референце

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