UUID是由一个16进制下的32位数所构成,故UUID理论上的总数为1632 =2128,约等于3.4 x 1038。也就是说若每纳秒(ns)产生1万亿个UUID,要花100亿年才会将所有UUID用完。
UUID的标准型式包含32个16进制数字,分为五段,形式为 8-4-4-4-12 的32个字符。示例:
550e8400-e29b-41d4-a716-446655440000
在其规范的文本表示中,UUID 的 16 个 8 位字节表示为 32 个十六进制(基数16)数字,显示在由连字符分隔 ‘-’ 的五个组中,“8-4-4-4-12” 总共 36 个字符(32 个字母数字字符和 4 个连字符)。
例如:
123e4567-e89b-12d3-a456-426655440000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
M
表示 UUID 版本, N
的一至三个最高有效位表示 UUID 变体。在例子中,M 是 1
, N 是 a
,这意味着此 UUID 是“变体1”、“版本1”UUID;即基于时间的 DCE/RFC 4122 UUID。
版本由 M 字符串中指示。
版本1 - UUID 是根据时间和 节点ID(通常是MAC地址)生成;
版本2 - UUID是根据标识符(通常是组或用户ID)、时间和节点ID生成;
版本3、版本5 - 确定性UUID 通过散列(hashing)名字空间(namespace)标识符和名称生成;
版本4 - UUID 使用随机性或伪随机性生成。
N那个位置,只会是8,9,a,b
M那个位置,代表版本号,由于UUID的标准实现有5个版本,所以只会是1,2,3,4,5
版本1的UUID,是根据 60-bit 的时间戳 和 节点(生成UUID的计算机)的 48-bitMAC地址而生成的。
优点:由于在算法中使用了MAC地址,这个版本的UUID可以保证在全球范围的唯一性。
缺点:因为它暴露了电脑的MAC地址和生成这个UUID的时间,这就是这个版本UUID被诟病的地方,使用MAC地址会带来安全性问题。一台机器部署多个实例可能会出现重复。
现在基本没人使用
DCE(Distributed Computing Environment)安全的UUID。和基于时间的UUID算法相同,但会把时间戳的前4位置换为POSIX的UID或GID。
不过,在UUID的规范里面没有明确地指定,所以基本上所有的UUID实现都不会实现这个版本。
版本3”和“版本5”的 UUID 被生成散列(hashing)一个名字空间标识符和一个名称。“版本3”使用 MD5 作为散列算法,“版本5”使用 SHA1。
根据随机数,或者伪随机数生成UUID。这种UUID产生有一定的重复概率但是极低,忽略不计;目前使用最多的版本。
Java只支持生成版本3和版本4的UUID
V4 随机UUID,UUID.randomUUID().toString()
V4 随机UUID重复概率问题?
V4随机版本有一定的重复概率但是极低,直接上结论,来着维基百科
在 103 万亿 个 版本4 UUID 中找到重复的概率是(十亿分之一)。
原始UUID的是32个字符长度 16进制存储,现在改为64进制存储,即base64,需要22个字符长度。即长度从原始的36降低到22,但是核心没变,只是变了展现形式。
原始的Base64包含+
和/
,其在url中会转义,但是使用url安全的则会自动替换为-
和 _
。
方式一 org.apache.commons.codec.binary.Base64
import org.apache.commons.codec.binary.Base64;
public static String uuidToBase64(String uuidStr) {
UUID uuid = UUID.fromString(uuidStr);
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return Base64.encodeBase64URLSafeString(bb.array());
}
public static String uuidFromBase64(String base64) {
byte[] bytes = Base64.decodeBase64(base64);
ByteBuffer bb = ByteBuffer.wrap(bytes);
UUID uuid = new UUID(bb.getLong(), bb.getLong());
return uuid.toString();
}
方式二 JDK8 java.util.Base64
import java.nio.ByteBuffer;
import java.util.Base64;
import java.util.UUID;
private static final Base64.Encoder BASE64_URL_ENCODER = Base64.getUrlEncoder().withoutPadding();
private static final Base64.Decoder BASE64_URL_DECODER = Base64.getUrlDecoder();
public static String uuidToBase64(String uuidStr) {
UUID uuid = UUID.fromString(uuidStr);
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return BASE64_URL_ENCODER.encodeToString(bb.array());
}
public static String uuidFromBase64(String base64) {
byte[] bytes = BASE64_URL_DECODER.decode(base64);
ByteBuffer bb = ByteBuffer.wrap(bytes);
UUID uuid = new UUID(bb.getLong(), bb.getLong());
return uuid.toString();
}
参考: