返回

ULID:一种高效简洁的唯一标识符

后端

导言

在现代软件系统中,生成唯一标识符(ID)至关重要。这些 ID 可用于跟踪用户、订单或任何其他需要唯一标识的实体。传统上,UUID(通用唯一标识符)是生成 ID 的流行选择,但它存在一些缺点,例如存储空间大、生成速度慢。

ULID(Universally Unique Lexicographically Sortable Identifier,通用唯一可按字典顺序排序的标识符)是一种较新的 ID 格式,旨在解决 UUID 的这些缺点。它不仅占用更少的存储空间,而且生成速度也更快,同时还保留了 UUID 的唯一性和排序特性。

ULID 规范

ULID 由以下部分组成:

  • 时间戳 (48 位) :以毫秒为单位表示自纪元(1970 年 1 月 1 日午夜)以来的时间。
  • 随机性 (80 位) :由伪随机数生成器 (PRNG) 生成的随机比特串。

ULID 的总长度为 128 位,通常表示为 26 个字符的字符串。字符集由大写字母 (A-Z)、小写字母 (a-z)、数字 (0-9) 和连字符 (-) 组成。

ULID 实现

我们可以基于 Java 语言实现 ULID。首先,我们需要一个伪随机数生成器 (PRNG)。Java 提供了 SecureRandom 类,我们可以使用它来生成安全的随机比特串。

接下来,我们需要将时间戳和随机性编码为字符串。我们可以使用 Base32 编码,它将 5 个二进制位编码为 8 个字符。

import java.security.SecureRandom;
import java.time.Instant;

public class Ulid {

    private static final SecureRandom RANDOM = new SecureRandom();
    private static final String BASE32_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    public static String generate() {
        // 获取当前时间戳
        long timestamp = Instant.now().toEpochMilli();

        // 生成随机性
        byte[] randomness = new byte[10];
        RANDOM.nextBytes(randomness);

        // 将时间戳编码为 Base32
        String timestampString = Base32.encode(timestamp);

        // 将随机性编码为 Base32
        String randomnessString = Base32.encode(randomness);

        // 返回 ULID 字符串
        return timestampString + randomnessString;
    }

    private static class Base32 {

        private static final char[] ALPHABET = BASE32_ALPHABET.toCharArray();

        public static String encode(long value) {
            StringBuilder sb = new StringBuilder();

            while (value > 0) {
                sb.append(ALPHABET[(int) (value % 32)]);
                value /= 32;
            }

            return sb.reverse().toString();
        }
    }
}

优势

ULID 具有以下优势:

  • 存储空间小: ULID 仅需 26 个字符,而 UUID 需要 36 个字符。
  • 生成速度快: ULID 的生成速度比 UUID 快,因为它不需要调用外部服务或复杂的算法。
  • 唯一性: 由于包含了时间戳和随机性,ULID 可以确保生成唯一 ID。
  • 可排序: ULID 按照时间顺序排序,这对于需要按时间检索或处理数据的应用程序非常有用。

应用场景

ULID 可用于各种应用场景,包括:

  • 数据库主键
  • 订单编号
  • 用户会话 ID
  • 日志跟踪

总结

ULID 是一种高效简洁的唯一标识符格式。它具有存储空间小、生成速度快、唯一性和可排序性的特点。通过 Java 语言的实现,我们可以深入了解 ULID 的底层原理,并将其应用于我们的项目中。