ULID Генератор - Креирајте Јединствене Сортабилне ИД-ове Онлајн Бесплатно
Бесплатни ULID генератор алат омогућава тренутно креирање јединствених, сортабилних идентификатора. Генеришите криптографски сигурне ULID-ове за базе података, АПИ-је и дистрибуиране системе онлајн.
ULID Генератор
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-а гради идентификатор у три корака.
- Очитајте тренутно време у милисекундама од почетка Unix епохе. То је број од 48 бита.
- Генеришите 80 бита случајних података, обично помоћу криптографски безбедног генератора случајних бројева, што даје 10 случајних бајтова.
- Кодирајте оба дела засебно помоћу Крокфордовог 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
| Особина | ULID | UUID (верзија 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-у су потребни само локални часовник и генератор случајних бројева, па се може у потпуности креирати ван мреже.
Референце
- "ULID Specification." GitHub, https://github.com/ulid/spec.
- "Crockford's Base32 Encoding." http://www.crockford.com/base32.html.