DEV Community

[yun]
[yun]

Posted on • Updated on

Java UUID 之路

什么是UUID?

UUID (Universally Unique Identifier) 是给于所有用途一个128位长的唯一值。

一般 UUID 标准使用Hex octets(十六位,八位字节)进度数字。
是由4个字符和4个“ - ”符号组成,综合长度是36个字符。
而所有位都设为0就是Nil UUID。

这里拿个栗子:
123e4567-e89b-42d3-a456-556642440000
xxxxxxxx-xxxx-Bxxx-Axxx-xxxxxxxxxxxx

A 表示确定 UUID 布局的变量。 UUID 中的所有其他位取决于变量字段中位的设置。变体由A的3个最重要位确定:

MSB1 MSB2 MSB3
0 X X reserved (0)
1 0 X current variant (2)
1 1 0 reserved for Microsoft (6)
1 1 1 reserved for future (7)

举例的 UUID 中的 A 值是'a'。 二进制等价物'a'(= 10xx)将变量显示为2。
B 代表版本。 举例的 UUID 中的版本(B的值)是4。

Java 提供的 UUID

UUID 布局变量为2 分别有5个版本:
v1: 基于时间 (Time Based),
v2: DCE安全性
v3,v5: 基于名称 (Name Based)
v4: 随机

Java 只提供了v3和v4 的 UUID implementation,但也提供了用于生成任何类型的UUID的构造函数:
UUID uuid = new UUID(long mostSigBits, long leastSigBits);

Java 也提供了获取 UUID 的变体和版本的方法:

UUID uuid = UUID.randomUUID();
int variant = uuid.variant();
int version = uuid.version();
Enter fullscreen mode Exit fullscreen mode

接下来我们来看看不同版本的 UUID 生成。

版本 3 & 5

v3 & 5 的 UUID 使用 namespace 和 name 的 hash 来进行生成。 namespace标识符可以是域名系统(DNS),对象标识符(OID),URL等。
UUID = hash(NAMESPACE_IDENTIFIER + NAME)

那么问题来了,v3和v5有什么区别呢?那就是 hash 算法,v3 使用得是 MD5 (128位) 而 v5 使用得是 SHA-1 (160位)。

那么问题又来了,UUID 不是128位而已吗?SHA1 有160位怎么办?
简而言之,我们将生成值散列截断为128位,然后将4位替换为版本,将2位替换为变量。

Java 只提供了 UUID v3 的生成,这里我们看看 Java 生成 UUID v3 的方法:

String source = namespace + name;
 byte[] bytes = source.getBytes("UTF-8");
 UUID uuid = UUID.nameUUIDFromBytes(bytes);
Enter fullscreen mode Exit fullscreen mode

版本 4

UUID v4 的生成是使用随机数作为源。 Java 是用 SecureRandom (使用不可预测的值作为种子来生成随机数以减少冲突的可能性) 来实现。
Java 生成 UUID v4 非常简单:

UUID uuid = UUID.randomUUID();

我们也可以使用 SHA-256 加上随机的 UUID 来使用:

MessageDigest salt = MessageDigest.getInstance("SHA-256");
 salt.update(UUID.randomUUID().toString().getBytes("UTF-8"));
 String digest = bytesToHex(salt.digest());
Enter fullscreen mode Exit fullscreen mode

总结

v3 和 v5 都具有不错的属性,不同的系统可以使用相同的 namespace 和 name 可以生成相同的UUID。 用于创建分层 UUID 是不错的选择。

如果只需要简单的UUID生成,那么使用 v4 就可以了。

Top comments (0)