定义
UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,目的是让分布式系统中的所有元素,都有唯一辨识,而不需要通过中央控制端来做辨识指定。
由算法机器生成。为保证UUID的唯一性,规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。UUID的复杂特性在保证了其唯一性的同时,意味着只能由计算机生成。
非人工指定,非人工识别。UUID是不能人工指定的,除非你冒着UUID重复的风险。UUID的复杂性决定了“一般人“不能直接从一个UUID知道哪个对象和它关联。
版本
UUID具有多个版本,每个版本的算法不同,应用范围也不同。
Version 1
基于时间的UUID。通过计算当前时间戳、随机数和机器MAC地址得到,由于在算法中使用了MAC地址,这个版本的UUID可以保证在全球范围的唯一性。但与此同时,使用MAC地址会带来安全性问题。如果应用只是在局域网中使用,也可以使用退化的算法,以IP地址来代替MAC地址。
Version 2
DCE(Distributed Computing Environment)安全的UUID。和基于时间的UUID算法相同,但会把时间戳的前4位置换为POSIX的UID或GID。
Version 3
基于名字的UUID(MD5)。通过计算名字和名字空间的MD5散列值得到。这个版本的UUID保证了:相同名字空间中不同名字生成的UUID的唯一性;不同名字空间中的UUID的唯一性;相同名字空间中相同名字的UUID重复生成是相同的。
Version 4
随机UUID。根据随机数,或者伪随机数生成UUID。这种UUID产生有一定的重复概率但是极低。
Version 5
基于名字的UUID(SHA1)。和版本3的UUID算法类似,只是散列值计算使用SHA1(Secure Hash Algorithm 1)算法。
应用
Version 1/2适合应用于分布式计算环境下,具有高度的唯一性。
Version 3/5适合于一定范围内名字唯一,且需要或可能会重复生成UUID的环境下。
Version4在数据量亿级以下或者唯一性要求不严谨的情况下使用。
Java中UUID提供了两个方法:randomUUID()和nameUUIDFromBytes(byte[] name),分别对应Version4和Version3。jdk实现如下
|
|
扩展
减小Version4重复概率
System.currentTimeMillis() + “_” + UUID.randomUUID().toString()生成结果示例:
可大幅度减少Version4的重复概率,缺点是拼接字符串后的值太长,长度为13(时间戳长度) + 1(连接字符) + 36(32位实际UUID加4位连接字符) = 50。
唯一id其他方案
以订单Id的解决方案为例
当前代码所在服务为单点服务且数据库唯一,数据库订单Id约束为unique。
若改为集群服务,数据库仍为单点,代码不变的情况下,可通过数据库异常保证订单Id的唯一性。若不通过异常排除,分布式下更好的方案为使用缓存如Redis或将订单Id的生成封装为单个服务。