1. UUID 介绍
UUID是由开放软件基金会(OSF)定义的用于唯一标识元素(软件包、硬件设备、数据库等)的识别码,被称为通用唯一识别码(Universally Unique Identifier)。
UUID固定格式:由4个连字号(-)将32个字节的字符串分隔后生成的字符串,总共36个字节。
例如:550e8400-e29b-41d4-a716-446655440000
1.1 UUID的特性
- 经由一定的算法机器生成
为了保证UUID的唯一性,规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。UUID的复杂特性在保证了其唯一性的同时,意味着只能由计算机生成。 - 非人工指定,非人工识别
UUID是不能人工指定的,除非你冒着UUID重复的风险。UUID的复杂性决定了“一般人“不能直接从一个UUID知道哪个对象和它关联。 - 在特定的范围内重复的可能性极小
UUID的生成规范定义的算法主要目的就是要保证其唯一性。但这个唯一性是有限的,只在特定的范围内才能得到保证,这和UUID的类型有关(参见UUID的版本)
1.2 UUID的版本
UUID的5个版本(开放软件基金会规范):
开放软件基金会(OSF)给出了UUID生成的规范,并未给出对应的实现代码。
- 一个特例 Nil UUID
通常我们不会用到它,它是由全为0的数字组成,如下:00000000-0000-0000-0000-000000000000 - UUID Version 1:基于时间的UUID
基于时间的UUID通过计算当前时间戳、随机数和机器MAC地址得到。由于在算法中使用了MAC地址,这个版本的UUID可以保证在全球范围的唯一性。但与此同时,使用MAC地址会带来安全性问题,这就是这个版本UUID受到批评的地方。如果应用只是在局域网中使用,也可以使用退化的算法,以IP地址来代替MAC地址--Java的UUID往往是这样实现的(当然也考虑了获取MAC的难度)。 - UUID Version 2:DCE安全的UUID
DCE(Distributed Computing Environment)安全的UUID和基于时间的UUID算法相同,但会把时间戳的前4位置换为POSIX的UID或GID。这个版本的UUID在实际中较少用到。 - UUID Version 3:基于名字的UUID(MD5)
基于名字的UUID通过计算名字和名字空间的MD5散列值得到。这个版本的UUID保证了:相同名字空间中不同名字生成的UUID的唯一性;不同名字空间中的UUID的唯一性;相同名字空间中相同名字的UUID重复生成是相同的。 - UUID Version 4:随机UUID
根据随机数,或者伪随机数生成UUID。这种UUID产生重复的概率是可以计算出来的,但随机的东西就像是买彩票:你指望它发财是不可能的,但狗屎运通常会在不经意中到来。 - UUID Version 5:基于名字的UUID(SHA1)
和版本3的UUID算法类似,只是散列值计算使用SHA1( Secure Hash Algorithm 1 )算法。
这里面常用的就是 UUID4 了,但是,即使是随机的,但是也是存在冲突的风险。
2 UUID的实现
- GUID全局唯一标识符:微软对UUID这个标准的实现,也是目前应用最广泛的版本。
- QTUUID生成器::QUuid类实现了UUID的生成、比较、转换等功能
- Java UUID生成器:java.util.UUID(JAVA、Android中还有很多第三方库可以生成UUID)
2.1 Java UUID生成器:java.util.UUID
UUID生成器官方文档
优点:Java自带,无需引入额外的库和依赖;简单易用,一行代码就可以生成UUID。
缺点:生成的UUID可能会重复,虽然重复的概率较小,但是在高并发的情况下还是有可能发生;
无法控制生成的UUID的格式,只能生成标准的UUID*/
import java.util.UUID;
public class UUIDGenerator {
public static void main(String[] args) {
//随机生成一个UUID对象
UUID uuid = UUID.randomUUID();
System.out.println("生成的UUID为:" + uuid.toString());
//通过给定的字符串名称和命名空间生成UUID对象
UUID uuid2 = UUID.nameUUIDFromBytes("example_name".getBytes());
System.out.println("生成的UUID2为:" + uuid2.toString());
}
}