Java中UUID的生成方法详解

8 次阅读

UUID(Universally Unique Identifier,通用唯一识别码)是软件开发中常用的一种唯一标识生成方式,广泛应用于数据库主键、分布式系统ID、文件名称、订单编号、接口请求标识等场景。Java提供了内置的UUID工具类,可以方便地生成符合标准格式的唯一字符串。

Java中的UUID生成方式主要依赖java.util.UUID类,该类基于RFC 4122标准实现,能够生成128位的唯一标识。UUID通常表现为32个十六进制字符,由4个短横线分隔,例如:

550e8400-e29b-41d4-a716-446655440000

一个标准UUID由五个部分组成:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

其中M表示UUID版本号,N表示变体信息。Java默认生成的是UUID版本4,也就是基于随机数生成的UUID。

Java使用UUID生成唯一标识

Java生成UUID最常用的方法是调用UUID.randomUUID()。

示例代码:

Java
import java.util.UUID;

public class UUIDDemo {
    public static void main(String[] args) {
        UUID uuid = UUID.randomUUID();

        System.out.println(uuid);
    }
}

运行结果:

9f8c6d52-5c8e-4e89-9d88-8c8c3e3a4f12

每次执行程序都会生成一个新的UUID。

UUID.randomUUID()返回的是UUID对象,如果需要字符串格式,可以调用toString()方法:

Java
String id = UUID.randomUUID().toString();

System.out.println(id);

输出:

d3b07384-d9a6-4d5f-8c72-4e4b7f5f8d21

这种方式是Java项目中最常见的UUID生成方式。

UUID生成字符串并去除横线

很多业务场景中,例如数据库字段、文件名或者接口参数,不希望UUID中包含短横线,可以通过字符串替换实现。

示例:

Java
String uuid = UUID.randomUUID()
        .toString()
        .replace("-", "");

System.out.println(uuid);

输出:

c6a7d4e91e564cbf8a3d8d5f6e7a9b10

去除短横线后的UUID长度为32位,更适合作为数据库字段存储。

例如MySQL中常见设计:

SQL
CREATE TABLE user (
    id VARCHAR(32) PRIMARY KEY,
    username VARCHAR(50)
);

Java插入数据时:

Java
String id = UUID.randomUUID()
        .toString()
        .replace("-", "");

这样可以避免数据库自增ID暴露业务增长规律。

Java UUID的常用方法介绍

java.util.UUID除了生成UUID外,还提供了一些常用操作方法。

获取UUID字符串

Java
UUID uuid = UUID.randomUUID();

String value = uuid.toString();

toString()会返回标准UUID格式。


获取UUID高64位和低64位

UUID实际上由两个64位数字组成:

Java
UUID uuid = UUID.randomUUID();

long most = uuid.getMostSignificantBits();
long least = uuid.getLeastSignificantBits();

System.out.println(most);
System.out.println(least);

这两个方法常用于底层存储优化。

例如数据库中可以使用两个BIGINT字段保存UUID,比VARCHAR存储更加节省空间。


根据字符串创建UUID

如果已经存在符合UUID格式的字符串,可以通过fromString()转换:

Java
String str = "550e8400-e29b-41d4-a716-446655440000";

UUID uuid = UUID.fromString(str);

System.out.println(uuid);

如果字符串格式错误,会抛出:

IllegalArgumentException

因此实际开发中通常需要提前校验输入。

UUID版本类型介绍

UUID标准定义了多个版本,不同版本生成方式不同。

UUID Version 1:基于时间生成

UUID v1主要根据:

  • 时间戳

  • 机器MAC地址

  • 时钟序列

生成唯一ID。

优点:

  • 时间有序

  • 重复概率极低

缺点:

  • 可能泄露机器信息

  • Java标准UUID类没有直接提供v1生成方法


UUID Version 3:基于名称和MD5

UUID v3根据命名空间和名称,通过MD5算法生成。

特点:

  • 同样输入生成相同UUID

  • 适合固定映射场景

例如:

Java
UUID uuid = UUID.nameUUIDFromBytes(
        "example".getBytes()
);

System.out.println(uuid);

Java中的nameUUIDFromBytes()默认生成UUID v3。


UUID Version 4:随机生成

Java中的:

Java
UUID.randomUUID()

生成的就是UUID v4。

特点:

  • 基于随机数

  • 不依赖机器信息

  • 使用简单

目前互联网应用中最常见。


UUID Version 5:基于SHA算法

UUID v5与v3类似,但使用SHA-1算法替代MD5。

Java标准库没有直接支持,需要使用第三方库实现。

UUID在实际项目中的应用场景

1. 数据库主键

UUID可以作为数据库唯一ID。

例如:

Java
@Entity
public class User {

    private String id = UUID.randomUUID()
            .toString();

}

相比自增ID,UUID具有:

  • 分布式生成能力

  • 不依赖数据库

  • 不容易被猜测

适合微服务架构。


2. 分布式系统ID生成

传统数据库自增ID在分布式环境中容易出现冲突。

例如:

订单服务:

订单ID:550e8400-e29b-41d4-a716-446655440000

不同服务器可以独立生成UUID,无需统一编号服务。


3. 文件唯一命名

上传文件时,为避免同名覆盖:

Java
String filename = UUID.randomUUID()
        + ".jpg";

生成:

a12bc456-789d-456e-b123-image.jpg

可以有效降低文件冲突概率。


4. 请求链路追踪

微服务调用过程中,可以生成UUID作为traceId:

Java
String traceId = UUID.randomUUID()
        .toString();

然后写入日志:

traceId=9f8c6d52-5c8e-4e89

方便排查跨服务问题。

UUID和雪花算法的区别

实际开发中,UUID经常会和雪花算法(Snowflake)进行比较。

对比项UUID雪花算法
长度128位64位
是否有序否是
是否依赖机器否是
数据库索引性能较低较高
分布式支持支持支持
可读性较差较好

UUID优势在于简单可靠,而雪花算法优势在于趋势递增和性能优化。

如果数据库使用UUID作为主键,随机写入可能导致B+Tree索引频繁分裂,影响性能。因此高并发业务通常会考虑:

  • 使用有序UUID

  • 使用雪花算法

  • 使用数据库自增ID

Java生成UUID时的注意事项

1. 不要认为UUID绝对不会重复

UUID设计目标是极低概率重复,并不是数学意义上的绝对唯一。

UUID v4理论重复概率极低,但关键业务仍可以增加数据库唯一约束。


2. 注意存储格式

UUID标准格式:

36个字符

去掉横线:

32个字符

数据库设计时应根据实际需求选择:

SQL
VARCHAR(36)

或者:

SQL
CHAR(32)

3. 避免频繁创建无意义UUID

UUID生成虽然开销较小,但大量循环生成时仍会产生额外计算成本。

例如:

Java
for(int i=0;i<1000000;i++){
    UUID.randomUUID();
}

如果只是临时计算,没有必要生成UUID。


4. 不要直接暴露敏感业务信息

UUID虽然不像自增ID那样容易推测数量,但它本身不是加密机制。

涉及安全认证时,应使用:

  • Token

  • 加密签名

  • 随机密钥

而不是单纯依赖UUID。

总结

Java中的UUID生成主要通过java.util.UUID实现,其中最常用的方法是UUID.randomUUID()。它能够快速生成符合标准的唯一标识,适用于用户ID、订单编号、文件名称、分布式系统标识等多种场景。

在普通业务开发中,UUID v4已经能够满足绝大多数唯一ID需求。但在高并发、大规模数据库场景下,需要结合索引性能、数据排序需求以及系统架构选择合适的ID方案。合理使用UUID,可以提升系统的扩展能力和数据管理效率。