UUID在Java中的实现与应用 您所在的位置:网站首页 mac地址和uuid UUID在Java中的实现与应用

UUID在Java中的实现与应用

2024-06-09 01:40| 来源: 网络整理| 查看: 265

UUID是什么

UUID的全称为:Universally Unique IDentifier,也被称为GUID(Globally Unique IDentifier)。是一种由算法生成的唯一标识,它实质上是一个128位长的二进制整数。通常表示成32个16进制数组成的字符串,如:21EC2020-3AEA-1069-A2DD-08002B30309D。关于UUID标准的rfc定义详见:http://www.ietf.org/rfc/rfc4122.txt。 当然,GUID一词有时也专指微软对UUID标准的实现,用于Windows操作系统中。

UUID的实现

UUID的格式是这样的:xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx,一共为32个16进制数。 M那个位置,代表版本号,目前UUID的标准实现有5个版本,所以只会是1,2,3,4,5 N那个位置,只会是8,9,a,b

UUID的具体实现存在多个版本,分别为:

1. 基于时间的UUID

基于时间的UUID通过计算当前时间戳、随机数和机器MAC地址得到。由于在算法中使用了MAC地址,这个版本的UUID可以保证在全球范围的唯一性。但与此同时,使用MAC地址会带来安全性问题,这就是这个版本UUID受到批评的地方。如果应用只是在局域网中使用,也可以使用退化的算法,以IP地址来代替MAC地址。

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

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

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

基于名称的UUID通过计算名称和名称空间的MD5散列值得到,这个版本的UUID保证了:相同名称空间中不同名称生成的UUID的唯一性;不同名称空间中的UUID的唯一性;相同名称空间中相同名称的UUID重复生成是相同的。

4. 基于随机数的UUID

根据随机数,或者伪随机数生成UUID。这种UUID产生重复的概率是可以计算出来的,但随机的东西就像是买彩票:你指望它发财是不可能的,但狗屎运通常会在不经意中到来。可能在测试的时候多线程并发也不见得出现重复,但是却不能保证系统正式上线之后不会出现不重复的UUID,特别是在分布式系统中。

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

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

在Java中默认实现了基于名称空间的UUID(UUID Version 3)和基于伪随机数的UUID(UUID Version 4),分别为:

/** * 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); } /** * 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); }

除了Java默认的实现之外,还有一个开源的UUID实现库可以参考:https://github.com/cowtowncoder/java-uuid-generator ,这个库支持实现UUID的V1,V3,V4和V5版本,在需要使用到唯一性ID的地方可以酌情考虑使用。

关于UUID使用的思考和总结

UUID是为了解决标识唯一性而提出的,这在分布式应用场景下非常常见。例如,用户登录Token,数据库记录主键ID等等。但是对于是否可以使用UUID(除了考虑唯一性之外,可能还要考虑有序性),以及使用哪个版本的UUID实现(考虑到效率等因素)需要慎重。例如:虽然UUID可以解决唯一性,但是却不适合直接用于数据库记录主键ID,对于数据库主键ID而言,除了考虑唯一性之外,还要考虑有序性,索引效率等因素。而在用户登录Token标识这种场景下使用UUID是可以的,甚至在使用手机或邮箱作为唯一名称标识的场景下,可以使用基于名称空间的UUID。 通常来讲,如果仅仅需要实现唯一性需求,那么对于使用UUID有如下建议:

对于暴露MAC地址不敏感的场合,使用UUID V1是最佳选择。当然了,也可以通过对UUID进行MD5散列的方式进行保密,不过这需要考虑性能开销。 如果可以保证在指定命名空间内的名称唯一性,例如手机号或者邮箱,那么选择UUID V3或者V5的实现也能保证唯一性。 对于UUID V4,如果是基于伪随机数的实现,是存在出现重复UUID的概率的,如果对于ID唯一性要求不是十分严格的场景,这个版本的实现也可以考虑。

另外,在各个语言平台对应UUID实现的支持各不相同。 1.Java语言 默认只支持V3和V4(基于伪随机数)两种版本的实现

2.Python语言 支持V1,V3,V4,V5版本的UUID实现 Python的UUID V1基于时间戳和MAC地址,最后12个16进制字符就是网卡地址。

>>> import uuid >>> uuid.uuid1() UUID('d3a173de-0ca9-11e8-af24-f0d5bf9aedc1') >>> uuid.uuid1() UUID('73e4ac9e-0caa-11e8-aa82-f0d5bf9aedc1')

Python支持UUID V3实现,对名称空间内的字符串进行MD5散列值生成UUID。

>>> uuid.uuid3(uuid.NAMESPACE_DNS,"chench") UUID('a0fda26d-acf1-37da-ad64-7cac7753de92') >>> uuid.uuid3(uuid.NAMESPACE_DNS,"chench") UUID('a0fda26d-acf1-37da-ad64-7cac7753de92')

Python的UUID V4实现基于伪随机数实现,这种UUID产生重复的概率是可以计算出来的。

>>> uuid.uuid4() UUID('d1437e20-95eb-446a-b9ca-9184013b8542') >>> uuid.uuid4() UUID('4dce6000-0ad5-4f35-84d8-6b434205d212')

与UUID V3的算法一致,不同的是UUID V5的散列算法为SHA1。

>>> uuid.uuid5(uuid.NAMESPACE_DNS,"chench") UUID('b8643db9-49d8-5a98-842d-14f3215f08cb') >>> uuid.uuid5(uuid.NAMESPACE_DNS,"chench") UUID('b8643db9-49d8-5a98-842d-14f3215f08cb')

【参考】 https://zh.wikipedia.org/wiki/通用唯一识别码 UUID https://zh.wikipedia.org/wiki/全局唯一标识符 GUID https://www.jianshu.com/p/d77f3ef0868a 关于UUID的二三事 https://qtdebug.com/java-duplicate-uuid/ 测试 Java 生成 UUID 是否重复 http://www.infoq.com/cn/articles/talk-about-the-history-of-uuid UUID简史



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有