什么是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();
接下来我们来看看不同版本的 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);
版本 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());
总结
v3 和 v5 都具有不错的属性,不同的系统可以使用相同的 namespace 和 name 可以生成相同的UUID。 用于创建分层 UUID 是不错的选择。
如果只需要简单的UUID生成,那么使用 v4 就可以了。
Top comments (0)