一种新的分布式ID生成方案--ULID

发布于:2025-08-02 ⋅ 阅读:(11) ⋅ 点赞:(0)

一种新的分布式ID生成方案
ULID: 一种新的分布式ID生成方案
ULID (Universally Unique Lexicographically Sortable Identifier) 是一种较新的分布式ID生成方案,旨在解决传统UUID和雪花算法(Snowflake)的一些局限性。

ULID的主要特点
可排序性:ULID按生成时间严格排序,便于数据库索引优化
128位兼容性:与UUID相同的128位长度(26字符Base32编码)
无特殊字符:仅使用Base32编码(字母A-Z和数字2-7)
跨语言支持:多种编程语言实现可用
单调递增:同一毫秒内生成的ULID也能保持顺序
ULID结构

在这里插入图片描述

在这里插入图片描述

适用场景
需要按时间排序的数据库主键
分布式系统需要无协调的ID生成
需要人类可读但不想暴露内部信息的ID
替换UUIDv4但需要排序能力的场景
各语言实现示例

javascript

// Node.js
const { ULID } = require('ulid');
const id = ULID(); // 01H5Z7K0G2ABC123DEF456GHJ

Python

import ulid
id = ulid.new()  # 01H5Z7K0G2ABC123DEF456GHJ

Java

// Java
import de.huxhorn.sulky.ulid.ULID;
ULID ulid = new ULID();
String id = ulid.nextULID(); // 01H5Z7K0G2ABC123DEF456GHJ

优缺点分析
优点:
无需中心化协调器
比UUID更友好的排序和索引性能
比Snowflake更简单的实现
时间信息可提取(前10字符代表时间)
缺点:
随机部分不如UUIDv4随机(时间部分固定)
相对较新,生态支持不如UUID广泛
80位随机性理论上存在冲突可能(但极低)
ULID为分布式系统ID生成提供了一个平衡了排序性、唯一性和易用性的新选择,特别适合需要时间排序的场景。

1. 添加依赖
首先添加 ULID 的 Java 实现库到你的项目中:
Maven 依赖

<dependency>
    <groupId>com.github.f4b6a3</groupId>
    <artifactId>ulid-creator</artifactId>
    <version>5.2.0</version> <!-- 检查最新版本 -->
</dependency>

2. 基本使用方法

import com.github.f4b6a3.ulid.Ulid;
import com.github.f4b6a3.ulid.UlidCreator;

public class UlidExample {
    public static void main(String[] args) {
        // 生成一个ULID
        Ulid ulid = UlidCreator.getUlid();
        System.out.println("ULID: " + ulid); // 例如: 01H5Z7K0G2ABC123DEF456GHJ
        
        // 获取ULID的不同部分
        System.out.println("Timestamp: " + ulid.getTimestamp()); // 48位时间戳
        System.out.println("Random: " + ulid.getRandom());       // 80位随机部分
        
        // 获取字符串表示
        String ulidString = ulid.toString();
        System.out.println("String: " + ulidString);
        
        // 从字符串解析ULID
        Ulid parsedUlid = Ulid.from(ulidString);
        System.out.println("Parsed: " + parsedUlid);
    }
}

3. 高级用法
单调递增ULID (同一毫秒内有序)

// 创建单调递增的ULID生成器
UlidCreator.Monotonic ulidMonotonic = UlidCreator.getMonotonicUlid();
// 同一毫秒内生成的ULID会保持顺序
Ulid ulid1 = ulidMonotonic.create();
Ulid ulid2 = ulidMonotonic.create();
System.out.println(ulid1.compareTo(ulid2) < 0); // 输出 true

自定义随机数生成器

import java.security.SecureRandom;

// 使用更安全的随机数生成器
SecureRandom secureRandom = new SecureRandom();
Ulid ulid = UlidCreator.getUlid(secureRandom);

获取时间信息

import java.time.Instant;

Ulid ulid = UlidCreator.getUlid();
Instant instant = ulid.getInstant(); // 获取生成时间
System.out.println("Created at: " + instant);

4. 性能优化
对于高性能场景,可以使用更高效的方法:

// 生成ULID并直接获取字节数组
byte[] bytes = new byte[16];
UlidCreator.getUlid(bytes); // 填充16字节数组
// 从字节数组创建ULID
Ulid fromBytes = Ulid.from(bytes);

5. 与UUID互转

import java.util.UUID;
// ULID转UUID
Ulid ulid = UlidCreator.getUlid();
UUID uuid = ulid.toUuid();
// UUID转ULID
Ulid fromUuid = Ulid.from(uuid);

6. 完整工具类示例

import com.github.f4b6a3.ulid.Ulid;
import com.github.f4b6a3.ulid.UlidCreator;

import java.time.Instant;
import java.util.UUID;

public class UlidUtils {
    
    /**
     * 生成标准ULID
     */
    public static String generate() {
        return UlidCreator.getUlid().toString();
    }
    
    /**
     * 生成单调递增ULID
     */
    public static String generateMonotonic() {
        return UlidCreator.getMonotonicUlid().create().toString();
    }
    
    /**
     * 获取ULID的生成时间
     */
    public static Instant getInstant(String ulid) {
        return Ulid.from(ulid).getInstant();
    }
    
    /**
     * ULID转UUID
     */
    public static UUID toUuid(String ulid) {
        return Ulid.from(ulid).toUuid();
    }
    
    /**
     * UUID转ULID
     */
    public static String fromUuid(UUID uuid) {
        return Ulid.from(uuid).toString();
    }
    
    /**
     * 验证字符串是否为有效ULID
     */
    public static boolean isValid(String ulid) {
        try {
            Ulid.from(ulid);
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}

7. 性能考虑
基准测试:在常规硬件上,ULID生成速度可达每秒数百万次
线程安全:UlidCreator是线程安全的
无阻塞:实现不依赖网络或IO操作

8. 注意事项
ULID区分大小写,但标准实现通常使用大写字母
时间戳部分基于UNIX时间戳(毫秒),可表示到10889年
随机部分使用安全的随机数生成器
在极高并发(同一毫秒内超过2^80次生成)时理论上可能冲突,但实际几乎不可能


网站公告

今日签到

点亮在社区的每一天
去签到