什么是 UUID,能保证唯一吗?

面试回答

UUID(Universally Unique Identifier)全局唯一标识符,是指这一台机器上生成的数字,它的目标是保证对在同一时空中的所有机器都是唯一的。

UUID 的生成是基于一定算法,通常使用的是随机数生成器或者基于时间戳的方式,生成的 UUID 由 32 位 16 进制数表示,共有 128 位(标准的UUID格式位:d80797aa-4ab9-4171-b832-3df8addb437e(8-4-4-4-12),共 32 个字符)

由于 UUID 是由 MAC 地址、时间戳、随机数等信息生成的,因此 UUID具有极高的唯一性,可以说是几乎不可能重复,但是在实际实现过程中,UUID 有多种实现版本,他们的唯一性指标也不尽相同。

UUID 在具体实现上,有多个版本,有基于时间的 UUID V1,基于随机数的 UUID V4 等。

Java 中的 java.util.UUID生成的 UUID 是 V3 和 V4 两种。

    /**
     * Static factory to retrieve a type 4 (pseudo randomly generated) UUID.
     *
     * The {@code UUID} is generated using a cryptographically strong pseudo
     * random number generator.
     *
     * @return  A randomly generated {@code UUID}
     */
    public static UUID randomUUID() {
        SecureRandom ng = Holder.numberGenerator;

        byte[] randomBytes = new byte[16];
        ng.nextBytes(randomBytes);
        randomBytes[6]  &= 0x0f;  /* clear version        */
        randomBytes[6]  |= 0x40;  /* set to version 4     */
        randomBytes[8]  &= 0x3f;  /* clear variant        */
        randomBytes[8]  |= 0x80;  /* set to IETF variant  */
        return new UUID(randomBytes);
    }
    /**
     * Static factory to retrieve a type 3 (name based) {@code UUID} based on
     * the specified byte array.
     *
     * @param  name
     *         A byte array to be used to construct a {@code UUID}
     *
     * @return  A {@code UUID} generated from the specified array
     */
    public static UUID nameUUIDFromBytes(byte[] name) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException nsae) {
            throw new InternalError("MD5 not supported", nsae);
        }
        byte[] md5Bytes = md.digest(name);
        md5Bytes[6]  &= 0x0f;  /* clear version        */
        md5Bytes[6]  |= 0x30;  /* set to version 3     */
        md5Bytes[8]  &= 0x3f;  /* clear variant        */
        md5Bytes[8]  |= 0x80;  /* set to IETF variant  */
        return new UUID(md5Bytes);
    }

优缺点

UUID 的优点就是他的性能比较高,不依赖网络,本地就可以生成,使用起来也比较简单。

但是他也有两个比较明显的缺点,那就是长度过长和没有任何含义。长度自然不必说,他有 32 位 16 进制数字。对于 d80797aa-4ab9-4171-b832-3df8addb437e这个字符串来说,我想任何一个程序员都看不出其表达的含义。一旦使用它作为全局唯一标识,就意味着在日后的问题排查和开发调试过程中会遇到很大的困难。

各个版本实现

V1.基于时间戳的 UUID

基于时间的 UUID 通过计算当前的时间戳、随机数和机器 MAC 地址得到。由于在算法中使用了 MAC 地址,这个版本的 UUID 可以保证在全球范围的唯一性。

但与此同时,使用 MAC 地址会带来安全性问题,这就是这个版本 UUID 受到批评的地方。如果应用知识在局域网中使用,也可以使用退化的算法,以 IP 地址来代替 MAC地址。

V2.DCE(Distributed Computing Environment)安全的 UUID

和基于时间的 UUID算法相同,但会把时间戳的前4位置换为 POSIX 的 UID 或 GID,这个版本的 UUID实际中较少用到。

V3.基于名称空间的 UUID(MD5)

基于名称的 UUID 通过计算名称和名称空间的 MD5 散列值得到。

这个版本的UUID保证了:相同名称空间中不同名称生成的UUID的唯一性;不同名称空间中的UUID的唯一性;相同名称空间中相同名称的 UUID重复生成得到的结果是相同的。

V4.基于随机数的 UUID

根据随机数,或者伪随机数生成 UUID。该版本 UUID 采用随机数生成器生成,它可以保证生成的 UUID 具有极佳的唯一性。但是因为基于随机数的,所以,并不适合数据量特别大的场景。

V5.基于名称空间的 UUID(SHA1)

和版本3的UUID算法类似,知识散列值计算使用 SHA1(Secure Hash Algorithm 1)算法。

各个版本总结

可以简单总结一下,Version 1 和 Version 2 这两个版本的 UUID,主要基于时间和 MAC 地址,所以比较适合应用于分布式计算环境下,具有高度唯一性。

Version 3 和 Version 5 这两种 UUID 都是基于名称空间的,所以在一定范围内是唯一的,而且如果有需要生成重复 UUID 的场景的话,这两种是可以实现的。

Version 4 这种是最简单的,只是基于随机数生成的,但是也是最不靠谱的。适合数据量不是特别大的场景下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

协享科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值