跳至主要內容

ULID:一种更友好的唯一标识符

逸尘.Lycodx大约 2 分钟后端ulid

ULID:一种更友好的唯一标识符

一、什么是 ULID ?

ULID(Universally Unique Lexicographically Sortable Identifier)是一种结合了时间戳和随机数的全局唯一标识符方案。

相比传统的 UUID 的优势

  • 可排序性: ULID 按时间顺序生成,可以方便地按时间排序。
  • 可读性: ULID 使用 Crockford's Base32 编码,比 UUID 的十六进制表示更易于阅读和记忆。
  • 唯一性: ULID 包含 48 位时间戳和 80 位随机数,保证了极高的唯一性。
  • 跨平台: ULID 的生成算法简单,易于在各种编程语言中实现。

ULID 凭借其天然的排序特性和良好的兼容性,正在成为现代应用开发中的优选 ID 方案。非常适合需要跨平台协作的项目。

二、ULID 结构解析

ULID 是一个 26 个字符的字符串,由以下部分组成:

  1. 时间戳 (10 个字符): 48 位整数,表示从 1970-01-01 00:00:00 UTC 开始的毫秒数。
  2. 随机数 (16 个字符): 80 位随机数,保证唯一性。
01AN4Z07BY      79KA1307SR9X4MV3
|----------|    |----------------|
 时间戳(48)     随机数(80)

三、 各语言生成实践

Go 语言

package main

import (
    "math/rand"
    "time"
    
    "github.com/oklog/ulid/v2"
)

func main() {
    entropy := rand.New(rand.NewSource(time.Now().UnixNano()))
    ms := ulid.Timestamp(time.Now())
    id, _ := ulid.New(ms, entropy)
    println(id.String()) // 01H5ZJQJG8P6S3QW4K4M7W0R2G
}

Python

import ulid

new_id = ulid.new()
print(str(new_id))  # 01H5ZJQJGHFN4MDVP3W5B0J6CX

PHP

<?php
use Ulid\Ulid;

require 'vendor/autoload.php';

// 生成新ULID
$ulid = Ulid::generate();
echo $ulid; // 01H5ZJQJGG3ZJ5M6KJ7Q8K9W0R

// 带时间戳生成
$timestamp = (int) (microtime(true) * 1000);
$ulid = Ulid::generate($timestamp);

Java

import de.huxhorn.sulky.ulid.ULID;

public class Main {
    public static void main(String[] args) {
        ULID ulid = new ULID();
        String id = ulid.nextULID(); 
        System.out.println(id); // 01H5ZJQJGH61ZR5T6X7P8Q9W0E
    }
}

四、关键特性对比

ULIDUUID
可排序性✅按时间戳❌ 随机
可读性✅ Base32❌ 十六进制
长度26字符36字符
冲突概率1e-211e-15

五、应用场景

  1. 数据库主键(特别适合时序数据)
  2. 分布式系统事件ID
  3. 日志追踪标识符
  4. 需要时间排序的目录结构

六、注意事项

  • 时间戳精度为毫秒级
  • 不建议用于密码学安全场景
  • 推荐结合 Monotonic Entropy 提高并发安全性
上次编辑于: