UUID和UUID在java的实现
UUID
概念&特点
UUID是Universally Unique IDentifier的缩写,翻译为通用唯一标识符或者全局唯一标识符。
UUID
是一种软件构建的标准,也是开放软件基金会组织在分布式计算环境领域的一部分。提出此标准的目的是:让分布式系统中的所有元素或者组件都有唯一的可辨别的信息,因为极低冲突频率和高效算法的基础,它不需要集中式控制和管理唯一可辨别信息的生成,由此,每个使用者都可以*地创建与其他人不冲突的UUID
。
目前有五种版本(具体到每个版本的更多信息这里就不展示了,有兴趣的可以自行上网查阅)
版本1:基于时间的UUID
版本2:DCE安全的UUID (和版本1类似)
版本3:基于名字的UUID(MD5)
版本4:基于加密的强随机数的UUID
版本5:基于名字的UUID(SHA1)
基本组成
UUID本质上是一个128位的数字,在规范文件描述中,UUID是由16个8比特数字,或者说32个16进制表示形式下的字符组成,一般表示形式为8-4-4-4-12,加上连接字符-一共有36个字符,例如:
//这串UUID是使用java给我们提供的方法生成的UUID(版本4)。
e84fb658-d356-44a1-9c7b-de2b4c43b71a
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx //M代表版本号,N代表变体编号
下面根据JDK1.6官方文档上的UUID的内容大致介绍下这串字符的具体构成(按照排列顺序)
属性 | 名称 | 长度(16进制) |
---|---|---|
time_low | 时间戳低位 | 8 |
time_mid | 时间戳中位 | 4 |
version& time_high | 版本号&时间戳高位 | 4 |
variant&clock_seq | 变体编号&时钟序列 | 4 |
node | 节点ID | 12 |
时间戳是使用数字签名技术产生的数据,签名的对象包括了原始文件信息、签名参数、签名时间等信息。时间戳系统用来产生和管理时间戳,对签名对象进行数字签名产生时间戳,以证明原始文件在签名时间之前已经存在。
下面是图片抽象化表示
注意:但这样的构造只适用于版本1和版本2,其他版本虽然结构一样,但无法获得时间戳、节点信息,落实到Java编程中的表现就是如果你尝试获取就会抛出异常,如下图API文档中描述。
特点
- 全局时空唯一性
随机产生的UUID(例如说由java.util.UUID类别产生的)的128个比特中,有122个比特是随机产生,4个比特在此版本(‘Randomly generated UUID’)被使用,还有2个在其变体(‘Leach-Salz’)中被使用。利用生日悖论,可计算出两笔UUID拥有相同值的机率约为:
以下是以x=2^122计算出UUID后产生碰撞的机率:
n | 机率 |
---|---|
2^36 | 4 x 10^-16 |
2^41 | 4 x 10^-13 |
2^46 | 4 x 10^-10 |
与被陨石击中的机率比较的话,已知一个人每年被陨石击中的机率估计为170亿分之1,也就是说机率大约是0.00000000006 (6 x 10^-11),等同于在一年内置立数十兆笔GUID并发生一次重复。换句话说,每秒产生10亿笔UUID,100年后只产生一次重复的机率是50%。如果地球上每个人都各有6亿笔GUID,发生一次重复的机率是50%。
- 生成效率高
使用UUID的主要原因之一是不需要集中式管理,其中一种格式限定了IEEE 802节点标识符,其他格式无此限制。可以自动化按需生成UUID,应用于多重不同的场景。UUID算法支持极高的分配速率,每台机器每秒钟可以生成超过1000万个UUID,因此它们可以作为事务ID使用。
UUID 在Java中的实现
四种生成方式
通过查阅Jdk1.6官方文档,可知java.util.UUID提供了四种生成UUID实例的方式:
-
最常见的就是调用静态方法UUID#randomUUID(),这就是版本4的静态工厂方法
-
其次是调用静态方法UUID#nameUUIDFromBytes(byte[] name),这就是版本3的静态工厂方法
-
另外有调用静态方法UUID#fromString(String name),这是解析8-4-4-4-12格式字符串生成UUID实例的静态工厂方法
-
还有低层次的构造函数UUID(long mostSigBits, long leastSigBits),这个对于使用者来说并不常见
注意事项
JDK中只提供了版本3 (MD5) 和版本4 (随机数)的UUID的实现,后面具体演示也会只针对这两种UUID。
代码演示
版本4,基于强随机数的UUID
public class UUIDTest {
public static void main(String[] args) {
//使用静态方法randomUUID(),方法返回值为UUID对象,使用toString()方法将UUID可视化转化为36长度的字符串
String s = UUID.randomUUID().toString();
System.out.println(s);
//实际使用中为方便数据库的操作可以用replace()方法去掉“-”
String s1 = s.replace("-","");
System.out.println(s1);
}
}
版本3,基于名称的UUID(MD5)
public class UUIDTest02 {
public static void main(String[] args) {
byte[] bytes = "ethan".getBytes(StandardCharsets.UTF_8);
//参数列表是一个字节数组,一般要求这个数组不重复即可。
String s = UUID.nameUUIDFromBytes(bytes).toString();
//得到的也是符合规范的UUID
System.out.println(s);
}
}
nameUUIDFromBytes(bytes).toString();
//得到的也是符合规范的UUID
System.out.println(s);
}
}
md文件百度云地址:https://pan.baidu.com/s/1potRzP6ynFkqb4QIlYw41A
提取码:6667