Generador de ULID - Crea Identificadores Únicos Ordenables Gratis en Línea
Herramienta gratuita de generación de ULID que crea identificadores únicos y ordenables al instante. Genere ULID criptográficamente seguros para bases de datos, API y sistemas distribuidos en línea.
Generador de ULID
Documentación
¿Qué es un ULID?
Un ULID (identificador lexicográficamente ordenable universalmente único) es un código de 26 caracteres que se utiliza para etiquetar registros en una base de datos o eventos en un sistema distribuido. Combina la hora actual con datos aleatorios, por lo que una lista de ULID ordenada alfabéticamente también queda ordenada según la hora de creación de cada uno. Un generador de ULID es una herramienta que produce estos códigos.
Estructura de un ULID
Un ULID tiene dos partes, escritas una a continuación de la otra y sin separador:
- Marca de tiempo (10 caracteres): el número de milisegundos transcurridos desde el 1 de enero de 1970 (la época Unix), con una capacidad de hasta 48 bits.
- Aleatoriedad (16 caracteres): 80 bits de datos aleatorios, añadidos para que dos ULID creados en el mismo milisegundo sigan siendo casi con total seguridad diferentes.
Ambas partes se escriben utilizando el alfabeto Base32 de Crockford: los dígitos del 0 al 9 y las letras de la A a la Z, excepto I, L, O y U. Esas cuatro letras se excluyen porque pueden confundirse con los dígitos 0 y 1, o entre sí. El resultado es una cadena corta, fácil de leer en voz alta y segura para incluir directamente en una URL.
Cómo se calcula un ULID
Un generador de ULID construye un identificador en tres pasos.
- Lee la hora actual en milisegundos desde la época Unix. Es un número de 48 bits.
- Genera 80 bits de datos aleatorios, normalmente mediante un generador de números aleatorios criptográficamente seguro, lo que proporciona 10 bytes aleatorios.
- Codifica ambas partes por separado utilizando el alfabeto Base32 de Crockford: la marca de tiempo de 48 bits se convierte en 10 caracteres y el valor aleatorio de 80 bits, en 16 caracteres. Las dos cadenas codificadas se unen para formar el ULID final de 26 caracteres.
La codificación funciona leyendo el número de 5 en 5 bits, porque cada carácter Base32 representa uno de 32 valores posibles (2^5 = 32). Diez caracteres contienen hasta 50 bits, espacio suficiente para la marca de tiempo de 48 bits. Dieciséis caracteres contienen exactamente 80 bits, lo que coincide con la parte aleatoria sin que sobre nada.
Ejemplo paso a paso
Supongamos que un generador de ULID se ejecuta en la marca de tiempo 1712345678901 (milisegundos desde la época) y obtiene los bytes aleatorios [12, 240, 88, 3, 199, 45, 6, 231, 128, 17].
Paso 1: codificar la marca de tiempo. Se divide repetidamente 1.712.345.678.901 entre 32, tomando el resto cada vez y leyendo los dígitos del último al primero (esta es la conversión estándar de base). El resultado es la cadena de 10 caracteres 01HTQW311N.
Paso 2: codificar la aleatoriedad. Se empaquetan los 10 bytes aleatorios en un flujo de 80 bits y, después, se leen 5 bits cada vez para convertir cada bloque de 5 bits en un carácter Base32. El resultado es la cadena de 16 caracteres 1KR5G0Y75M3EF00H.
Paso 3: unir las partes. El ULID final es:
101HTQW311N 1KR5G0Y75M3EF00H
2Escrito sin el espacio: 01HTQW311N1KR5G0Y75M3EF00H, con 26 caracteres en total.
Uso de este generador
El generador se ejecuta en el navegador. Cada ULID se construye a partir del reloj del navegador y de 80 bits aleatorios nuevos obtenidos del generador criptográfico de números aleatorios del navegador, por lo que ningún identificador se envía a un servidor ni se obtiene de él.
- Número de ULID acepta un número entero del 1 al 50. El valor predeterminado es 1.
- Generar ULID produce un lote nuevo. Cambiar la cantidad también produce un lote nuevo.
- Copiar, en un resultado, copia ese ULID individual. Cuando se muestra más de uno, Copiar todo copia la lista completa, con un ULID por línea.
- Restablecer devuelve la cantidad a 1 y genera un ULID nuevo.
Debajo de los resultados, el panel Estructura del ULID divide el primer ULID del lote en sus dos partes: los primeros 10 caracteres (la marca de tiempo) y los últimos 16 (la parte aleatoria).
ULID frente a UUID
| Característica | ULID | UUID (versión 4) |
|---|---|---|
| Longitud | 26 caracteres | 36 caracteres (con guiones) |
| Ordenable por hora de creación | Sí | No |
| Codificación | Base32 de Crockford | Hexadecimal |
| Contiene una marca de tiempo | Sí (48 bits) | No |
| Seguro para URL sin necesidad de escape | Sí | Sí |
Ambos formatos buscan producir identificadores únicos entre sistemas sin que una autoridad central asigne los números. La principal diferencia práctica es la ordenación: como un ULID comienza con una marca de tiempo, ordenar ULID como texto simple también los ordena por hora. Un UUID aleatorio no tiene esta propiedad, porque todas sus partes son aleatorias.
Usos habituales
- Claves primarias de bases de datos: los ULID permiten que una base de datos indexe las filas nuevas aproximadamente en el orden en que se insertaron, algo que muchos motores de bases de datos gestionan de forma más eficiente que las claves completamente aleatorias.
- Sistemas distribuidos: varios servidores pueden generar ULID de forma independiente, sin coordinarse con un contador central, y los resultados siguen siendo casi con total seguridad únicos.
- Registros de eventos: como los ULID se ordenan por hora, una lista de identificadores de eventos también puede servir como una cronología aproximada.
- Identificadores de API y archivos: el formato fijo de 26 caracteres, seguro para URL, funciona correctamente en direcciones web y nombres de archivo.
Entre los formatos de identificadores relacionados se encuentran KSUID, que también codifica una marca de tiempo para permitir la ordenación, y los identificadores Snowflake, utilizados por Twitter y otros servicios, que combinan una marca de tiempo, un identificador de máquina y un contador.
Ejemplos de código
Cada ejemplo siguiente construye un ULID de la misma manera descrita en la especificación de ULID: codifica la marca de tiempo de 48 bits como 10 caracteres Base32 de Crockford, codifica 80 bits de aleatoriedad como otros 16 caracteres y los une.
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}
41Preguntas frecuentes
¿Para qué se utiliza un ULID?
Un ULID se utiliza como identificador único de una fila de base de datos, un recurso de API o un evento registrado, cuando también resulta útil ordenar por hora de creación.
¿Cuánto mide un ULID?
Un ULID siempre tiene 26 caracteres: 10 para la marca de tiempo y 16 para la parte aleatoria.
¿Qué codificación utiliza un ULID?
Un ULID utiliza el alfabeto Base32 de Crockford, formado por los dígitos del 0 al 9 y las letras de la A a la Z, con I, L, O y U eliminadas para evitar confusiones con otros caracteres.
¿En qué se diferencia un ULID de un UUID?
Un ULID se ordena por hora de creación y tiene 26 caracteres. Un UUID aleatorio (versión 4) no se ordena por hora y tiene 36 caracteres, incluidos los guiones.
¿Qué probabilidad hay de que dos ULID coincidan?
Los 80 bits de aleatoriedad hacen que las coincidencias sean extremadamente improbables. Sería necesario generar aproximadamente 1,3 billones de ULID dentro del mismo milisegundo para alcanzar una probabilidad del 50 % de que dos coincidieran.
¿Se pueden generar ULID sin conexión a Internet?
Sí. Un ULID solo necesita el reloj local y un generador de números aleatorios, por lo que puede crearse completamente sin conexión.
Referencias
- «Especificación de ULID». GitHub, https://github.com/ulid/spec.
- «Codificación Base32 de Crockford». http://www.crockford.com/base32.html.