Trình tạo ULID

Tạo ID duy nhất có thể sắp xếp theo thứ tự từ điển

Số lượng

Nhấn Tạo để tạo ULID

ULID là gì?

ULID (Universally Unique Lexicographically Sortable Identifier) là định dạng định danh 128-bit được thiết kế để vừa duy nhất vừa có thể sắp xếp một cách tự nhiên.

ULID được mã hóa sử dụng bảng chữ cái Crockford's Base32, tạo ra chuỗi 26 ký tự nhỏ gọn, URL-safe, không phân biệt chữ hoa chữ thường và không có các ký tự mơ hồ về mặt hình ảnh.

Thông số kỹ thuật ULID được tạo bởi Alizain Feerasta và được sử dụng rộng rãi trong các hệ thống phân tán, event sourcing và khóa chính database.

Cấu trúc ULID

ULID rộng 128 bit, được chia thành hai thành phần:

TimestampNgẫu nhiên
01ARZ3NDEKTSVE4RRFFQ69G5FAV
48 bit — Timestamp Unix tính bằng mili giây. Mã hóa thời gian tạo với độ chính xác 1ms. Bao gồm các ngày đến năm 10889.80 bit — dữ liệu ngẫu nhiên an toàn về mặt mật mã. Được tái tạo mới cho mỗi ULID (trừ khi sử dụng chế độ đơn điệu).

Được mã hóa dưới dạng 26 ký tự Crockford Base32: 10 ký tự đầu tiên đại diện cho timestamp, 16 ký tự cuối đại diện cho thành phần ngẫu nhiên.

Bảng chữ cái Crockford Base32

ULID sử dụng mã hóa Crockford's Base32, sử dụng 32 trong 36 ký tự chữ số. Bảng chữ cái là: 0123456789ABCDEFGHJKMNPQRSTVWXYZ

Tại sao 32 ký tự này?
0123456789ABCDEFGHJKMNPQRSTVWXYZ

Bốn ký tự bị loại trừ có chủ ý:

  • IL bị loại trừ — dễ nhầm lẫn với chữ số 1
  • O bị loại trừ — dễ nhầm lẫn với chữ số 0
  • U bị loại trừ — tránh các từ thô tục vô tình trong ID được tạo
  • Mã hóa không phân biệt chữ hoa chữ thường01ARZ3NDEKTSV4RRFFQ69G5FAV01arz3ndektsv4rrffq69g5fav là cùng ULID

Crockford Base32 hiệu quả hơn hệ thập lục phân (32 ký hiệu so với 16) và dễ đọc hơn Base64 cho con người.

ULID so với UUID

ULID và UUID đều đại diện cho các định danh 128-bit, nhưng khác nhau đáng kể về mã hóa và mục tiêu thiết kế:

Thuộc tínhULIDUUID
Định dạngCrockford Base32Hex có gạch nối
Độ dài26 ký tự36 ký tự
TimestampUnix ms 48-bitKhông có (v4) hoặc ms 48-bit (v7)
Có thể Sắp xếpCó — theo thứ tự từ điểnKhông (v4) / Có (v7)
URL-safeCó (chỉ chữ số)Có (với dấu gạch nối)
Phụ thuộcYêu cầu thư việnGốc (crypto.randomUUID)
Hỗ trợ DBLưu dưới dạng CHAR(26) hoặc BINARY(16)Kiểu cột UUID gốc
Thông số kỹ thuậtThông số kỹ thuật cộng đồng (ulid.github.io)RFC 4122 / RFC 9562

Nếu bạn đã trong hệ sinh thái UUID (các cột uuid PostgreSQL, REST API), UUID v7 thường phù hợp hơn ULID. Nếu bạn thích mã hóa thân thiện với con người hơn, ULID là lựa chọn xuất sắc.

ULID so với nanoid

Cả ULID và nanoid đều tạo ra các định danh ngắn, URL-safe, nhưng có các mục tiêu thiết kế khác nhau:

Thuộc tínhULIDNanoID
TimestampCó — Unix ms 48-bitKhông
Có thể Sắp xếpKhông
Độ dài mặc định26 ký tự21 ký tự
Entropy80 bit (thành phần ngẫu nhiên)~126 bit
Bảng chữ cáiCrockford Base32 (32 ký tự)URL-safe Base64 (64 ký tự)
Độ dài có thể tùy chỉnhKhôngCó (độ dài bất kỳ)
Trường hợp sử dụngID theo thứ tự thời gian, khóa chính DBToken ngẫu nhiên, URL ngắn, khóa API

Chọn ULID khi bạn cần sắp xếp theo thời gian. Chọn nanoid khi bạn muốn entropy tối đa trong chuỗi ngắn, ngẫu nhiên.

Sử dụng ULID trong Database

ULID có thể được lưu trong database theo nhiều cách tùy thuộc vào yêu cầu của bạn:

Lưu dưới dạng CHAR(26)
Cách tiếp cận đơn giản nhất. Thứ tự sắp xếp theo từ điển được bảo toàn.
Lưu dưới dạng BINARY(16)
Giải mã ULID sang biểu diễn nhị phân 16 byte để lưu trữ nhỏ gọn.
PostgreSQL
Lưu dưới dạng CHAR(26) hoặc sử dụng kiểu bytea cho lưu trữ nhị phân.
MySQL / MariaDB
Sử dụng CHAR(26) CHARACTER SET ascii để lưu trữ hiệu quả.
SQLite
Lưu dưới dạng TEXT. So sánh văn bản mặc định của SQLite sắp xếp ULID đúng cách.
MongoDB
Lưu dưới dạng trường chuỗi. Khả năng sắp xếp theo từ điển của ULID hoạt động tự nhiên với so sánh chuỗi của MongoDB.

Ví dụ Mã

Tạo ULID yêu cầu thư viện ulid (có sẵn cho JavaScript, Python, Go, Rust, và nhiều hơn nữa):

JavaScript (ulid npm)
// Using the 'ulid' npm package
import { ulid } from 'ulid'

const id = ulid()          // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
const id2 = ulid()         // "01ARZ3NDEKXXXXXXXXXXXX..." (same ms, incremented random)

// With a custom timestamp
const id3 = ulid(1469918176385) // deterministic time portion

// Extract the timestamp back out
import { decodeTime } from 'ulid'
decodeTime(id)  // → 1469918176385 (Unix ms)
Python (python-ulid)
# Using python-ulid
from ulid import ULID

uid = ULID()
str(uid)                    # "01ARZ3NDEKTSV4RRFFQ69G5FAV"
uid.timestamp               # 1469918176.385
uid.datetime                # datetime(2016, 7, 30, 23, 36, 16, 385000, tzinfo=timezone.utc)

# Parse an existing ULID string
parsed = ULID.from_str("01ARZ3NDEKTSV4RRFFQ69G5FAV")
parsed.timestamp            # 1469918176.385
PostgreSQL
-- Store ULIDs as TEXT or CHAR(26)
CREATE TABLE events (
  id   CHAR(26) PRIMARY KEY DEFAULT gen_ulid(),  -- if using a PG extension
  name TEXT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Or pass the ULID from your application layer
INSERT INTO events (id, name, created_at)
VALUES ('01ARZ3NDEKTSV4RRFFQ69G5FAV', 'user.signup', NOW());

-- Range queries are efficient because ULIDs sort chronologically
SELECT * FROM events
WHERE id > '01ARZ3NDEKTSV4RRFFQ69G5FAV'
ORDER BY id
LIMIT 20;
JavaScript (pure — no dependencies)
// Pure browser / Deno / Node.js implementation (no dependencies)
const CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'

function encodeTime(ms) {
  let result = '', n = BigInt(ms)
  for (let i = 9; i >= 0; i--) {
    result = CROCKFORD[Number(n & 31n)] + result
    n >>= 5n
  }
  return result
}

function encodeRandom(bytes) {
  let n = 0n
  for (const b of bytes) n = (n << 8n) | BigInt(b)
  let result = ''
  for (let i = 15; i >= 0; i--) {
    result = CROCKFORD[Number(n & 31n)] + result
    n >>= 5n
  }
  return result
}

function generateULID() {
  const randomBytes = new Uint8Array(10)
  crypto.getRandomValues(randomBytes)
  return encodeTime(Date.now()) + encodeRandom(randomBytes)
}

Câu hỏi Thường gặp

ULID có duy nhất toàn cầu không?
Có — với xác suất rất cao. Thành phần ngẫu nhiên 80-bit cung cấp 2^80 ≈ 1,2 × 10^24 giá trị có thể mỗi mili giây mỗi bộ tạo.
ULID có giống với UUID không?
Không — ULID và UUID là các mã hóa khác nhau của giá trị 128-bit.
Chế độ đơn điệu ULID hoạt động như thế nào?
Trong chế độ tiêu chuẩn, thành phần ngẫu nhiên 80-bit được tạo mới cho mỗi ULID. Trong chế độ đơn điệu, khi nhiều ULID được tạo trong cùng mili giây, thành phần ngẫu nhiên được tăng lên.
Tôi có thể giải mã ULID để lấy timestamp tạo không?
Có. 10 ký tự Crockford Base32 đầu tiên mã hóa timestamp Unix mili giây 48-bit.
ULID có phải là tiêu chuẩn chính thức không?
Không. ULID là thông số kỹ thuật cộng đồng được duy trì tại ulid.github.io. Đây không phải là tiêu chuẩn IETF như UUID.