还在用uuid ,ulid来了

简介: 还在用uuid ,ulid来了

ULID(Universally Unique Lexicographically Sortable Identifier)是一种能够生成全局唯一的识别码的方法,具有以下优点:

  1. 全局唯一性:ULID生成的识别码具有全局唯一性,不同机器、不同时间、不同线程、不同进程生成的ULID都不会重复。
  2. 高容量:ULID由128位二进制数表示,相对于传统的UUID(只有128位)能够容纳更多的信息。
  3. 可排序:ULID具有词典序(字典序)排序特性,当两个ULID做比较时,按照字符顺序比较即可得到正确的排序结果。
  4. 高性能:ULID的生成速度比传统的UUID更快,使用标准的开源实现一次生成的时间不到毫秒级别。
  5. 高可读性:ULID采用了很多不易混淆的字符,具有一定的可读性,便于在日志、调试信息中使用。

ULID是一种高效、全局唯一、可排序、容量大、可读性强的识别码生成算法,适合于分布式环境下的唯一标识生成。

UUID (Universally Unique Identifier) 和 ULID (Universally Unique Lexicographically Sortable Identifier) 都是用来生成唯一标识符的算法,但它们在实现方式上有所不同。

UUID 是一种由标准化组织制定的标识符生成算法,它通过 MAC 地址、时间戳、命名空间和随机数等数据生成,保证了生成的标识符的唯一性。它的长度为 128 位,通常表示为 32 个十六进制数字,其中包含 4 个破折号,如:“550e8400-e29b-41d4-a716-446655440000”。

ULID 是基于时间和随机数生成的标识符算法,它的结构是包含了时间戳的 48 位前缀和 80 位随机数后缀,共计 128 位。ULID 也可以表示为 32 个字符的字符串,而且这个字符串是根据时间戳顺序排列的,因此可以用作排序和索引。

总的来说,UUID 和 ULID 都是用来生成唯一标识符的算法,但它们的实现方式、长度、格式等方面存在差异。选择使用哪种算法取决于场景需求,如果需要标识符完全随机且数量大到足以保证唯一性,使用 UUID 就可以了;如果需要标识符的排序和索引,并且时间戳是必须的,那么可以使用 ULID。


ULID (Universally Unique Lexicographically Sortable Identifier) 是一个可排序且唯一的标识符,它由时间戳和随机数生成。相较于 UUID,ULID 可以更好地支持分布式系统的排序和查询。以下是 Java 实现 ULID 的示例代码:


java
import java.security.SecureRandom;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicLong;
public class ULIDGenerator {
    private static final long EPOCH = Instant.parse("2021-01-01T00:00:00Z").toEpochMilli();
    private static final char[] ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ".toCharArray();
    private static final int ENCODING_LENGTH = ENCODING.length;
    private static final int TIMESTAMP_LENGTH = 10;
    private static final int RANDOMNESS_LENGTH = 16;
    private static final AtomicLong LAST_TIMESTAMP_MS = new AtomicLong(Long.MIN_VALUE);
    private static final SecureRandom RANDOM = new SecureRandom();
    public static String generateULID() {
        long timestampMs = getCurrentTimestampMs();
        StringBuilder sb = new StringBuilder(TIMESTAMP_LENGTH + RANDOMNESS_LENGTH);
        encodeLong(timestampMs - EPOCH, sb, TIMESTAMP_LENGTH); // 时间戳
        encodeLong(generateRandomness(), sb, RANDOMNESS_LENGTH); // 随机数
        return sb.toString();
    }
    private static long getCurrentTimestampMs() {
        long now = Instant.now().toEpochMilli();
        while (true) {
            long lastTimestampMs = LAST_TIMESTAMP_MS.get();
            if (now > lastTimestampMs) {
                if (LAST_TIMESTAMP_MS.compareAndSet(lastTimestampMs, now)) {
                    return now;
                }
            } else {
                return LAST_TIMESTAMP_MS.incrementAndGet();
            }
        }
    }
    private static long generateRandomness() {
        byte[] randomness = new byte[8];
        RANDOM.nextBytes(randomness);
        return bytesToLong(randomness);
    }
    private static void encodeLong(long value, StringBuilder sb, int length) {
        sb.setLength(length);
        for (int i = length - 1; i >= 0; i--) {
            sb.setCharAt(i, ENCODING[(int) (value % ENCODING_LENGTH)]);
            value /= ENCODING_LENGTH;
        }
    }
    private static long bytesToLong(byte[] bytes) {
        long value = 0;
        for (byte b : bytes) {
            value = (value << 8) | (b & 0xff);
        }
        return value;
    }
}


上述代码使用了 SecureRandom 生成 128 位的随机数,然后使用自定义的一种 32 个字符的编码(0123456789ABCDEFGHJKMNPQRSTVWXYZ)对随机数和时间戳进行编码。时间戳表示自“2021-01-01T00:00:00Z”以来经过的毫秒数,长度为 10 个字符。到达极限时,ULID 可以支持生成超过 3.4e+38 个 ID,每秒达到 280 万个 ID 的生成速度。

需要注意的是,由于 ULID 是有序的,所以在高并发的场景下,使用静态的 LAST_TIMESTAMP_MS 可能会成为瓶颈,可以考虑使用类似 AtomicLong 的原子变量来保证并发安全。

目录
相关文章
|
1月前
|
存储 C# 数据库
C# 生成唯一ID,有哪些方法?
【2月更文挑战第12天】
340 0
|
8月前
|
自然语言处理 Java Go
ULID 在 Java 中的应用: 使用 `getMonotonicUlid` 生成唯一标识符
ULID 在 Java 中的应用: 使用 `getMonotonicUlid` 生成唯一标识符
266 0
|
1月前
|
Java API
List转Map(id为key,list为value)
List转Map(id为key,list为value)
45 0
|
1月前
|
算法 云计算 索引
生成UUID和自定义UUID算法
生成UUID和自定义UUID算法
170 0
|
8月前
|
自然语言处理 安全 Unix
了解一下新工具ULID?
了解一下新工具ULID?
203 0
|
安全
IDOR绝不止他人的 ID
目标中有这样一个功能,免费用户最多可以同时创建 3 个列表。如果您发送创建三个以上列表的请求,该站点将授予普通用户选择 3 个列表并锁定第 4 个和其他列表的权利。此外,无法管理、添加或删除、共享或重命名锁定列表。
86 0
IDOR绝不止他人的 ID
UUID.randomUUID().toString() 生成主键 介绍与使用
UUID.randomUUID().toString() 介绍 UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法。 UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字 它保证对在同一时空中的所有机器都是唯一的 是由一个十六位的数字组成,表现出来的形式
184 0
uuid v4
第四版uuid
282 0
高性能高并发的生成唯一的Id
高性能高并发的生成唯一的Id
93 0