找回密码
 会员注册
查看: 19|回复: 0

聊聊UUID

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64122
发表于 2024-10-12 09:47:44 | 显示全部楼层 |阅读模式
格式UUID(universally unique identifier) 长度是128 bit,也就是由32个16进制数值组成。其中 M 表示 version,N 表示 Variants xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx。例如:5aadc328-8d5e-11ec-8a00-acde48001122版本Version 1 (date-time and MAC address)Version 2 (date-time and MAC address, DCE security version)Versions 3 and 5 (namespace name-based)Version 4 (random)Version 1 (date-time and MAC address)version1 的 UUID 是基于时间戳和 Mac 地址的。先用 ifconfig -v en9查看一下 Mac地址为:acde48001122en9:flags=8863mtu1500index4eflags=21000080etherac:de:48:00:11:22inet6fe80::aede:48ff:fe00:1122%en9prefixlen64scopeid0x4nd6options=201 media:autoselect(100baseTX)status:activetype:Ethernetlinkquality:100(good)stateavailability:0(true)scheduler:FQ_CODELlinkrate:100.00Mbpsqosmarkingenabled:nomode:none用 Python 生成的 UUID>>>importuuid;>>>uuid.uuid1();UUID('5aadc328-8d5e-11ec-8a00-acde48001122')Java 在 JDK 的工具包中,默认只提供了 V3 和 V4 版本的UUID实现。V3publicstaticUUIDnameUUIDFromBytes(byte[]name){MessageDigestmd;try{md=MessageDigest.getInstance("MD5");}catch(NoSuchAlgorithmExceptionnsae){thrownewInternalError("MD5notsupported",nsae);}byte[]md5Bytes=md.digest(name);md5Bytes[6]&=0x0f;/*clearversion*/md5Bytes[6]|=0x30;/*settoversion3*/md5Bytes[8]&=0x3f;/*clearvariant*/md5Bytes[8]|=0x80;/*settoIETFvariant*/returnnewUUID(md5Bytes);}V4publicstaticUUIDrandomUUID(){SecureRandomng=Holder.numberGenerator;byte[]randomBytes=newbyte[16];ng.nextBytes(randomBytes);randomBytes[6]&=0x0f;/*clearversion*/randomBytes[6]|=0x40;/*settoversion4*/randomBytes[8]&=0x3f;/*clearvariant*/randomBytes[8]|=0x80;/*settoIETFvariant*/returnnewUUID(randomBytes);}我们依赖一个 Java 库来看一下生成的 V1 版本的 UUID,依赖如下:com.fasterxml.uuidjava-uuid-generator4.0.1生成 V1 版本的 UUID。java-uuid-generatorUUIDuuid=Generators.timeBasedGenerator().generate();991c146f-8f07-11ec-93eb-3d5453c2d114可以看到 Python 生成的 UUID 和 Java 生成的 UUID 的 Mac 地址并不相同。Python 是真实的 Mac 地址,如果我们去看 Java 的生成代码会发现,它的 Mac 地址是随机生成的。我们分析一下 5aadc328-8d5e-11ec-8a00-acde48001122的结构名称实例长度(hex digits)说明time_low5aadc3288time_mid8d5e4time_hi_and_version11ec41(version)+1ec(time_hi)variant and clock_sequence8a0041 to 3-bit "variant" in the most significant bits, followed by the 13 to 15-bit clock sequence (from wikipedia)This field is composed of a varying number of bits. 0 - - Reserved for NCS backward compatibility 1 0 - The IETF aka Leach-Salz variant (used by this class) 1 1 0 Reserved, Microsoft backward compatibility 1 1 1 Reserved for future definition. (from Java comments)clock sequence 目的是为了避免重复,理解为随机数据就好 | | node | acde48001122 | 12 | Mac地址 |根据 time_low、time_mid、time_hi 我们计算一下 UUID 的生成时间。首先拼接出完成时间 time_hi+time_mid+time_low 即 1ec+8d5e+5aadc328 转换成十进制然后在通过 Java 获取一下时间戳,可以发现是一致的。UUIDuuid=UUID.fromString("5aadc328-8d5e-11ec-8a00-acde48001122");System.out.println(uuid.timestamp());138641124929422120看看时间戳是怎么来的,它是从 **1582年10月15日 **开始每隔100纳秒加1。★being the number of 100-nanosecond intervals since midnight 15 October 1582 Coordinated Universal Time (UTC), the date on which the Gregorian calendar was first adopted”最后再来转成当前的时间:UUIDuuid=UUID.fromString("5aadc328-8d5e-11ec-8a00-acde48001122");CalendaruuidEpoch=Calendar.getInstance(TimeZone.getTimeZone("UTC"));uuidEpoch.clear();uuidEpoch.set(1582,9,15,0,0,0);//9=OctoberlongepochMillis=uuidEpoch.getTime().getTime();longtime=(uuid.timestamp()/10000L)+epochMillis;System.out.println(time);1644819692942Version 2 (date-time and MAC address, DCE security version)UUID Version 2 与 Version 1 类似,Version 2 的 clock_sequence 的低 8 位和 timestamp 的最低 32 位进行了修改,关于 Version 2,RFC 4122 提供的信息也比较少,有的语言也没有实现 UUID Version 2。Python2.7.18>>>importuuid;>>>uuid.uuid1();UUID('5aadc328-8d5e-11ec-8a00-acde48001122')>>>>>>uuid.uuid2();Traceback(mostrecentcalllast):File"",line1,inAttributeError:'module'objecthasnoattribute'uuid2'Versions 3 and 5 (namespace name-based)v3 和 v5 都是基于 namespace 的 v3 = MD5(namespace)Javav3实现publicstaticUUIDnameUUIDFromBytes(byte[]name){MessageDigestmd;try{md=MessageDigest.getInstance("MD5");}catch(NoSuchAlgorithmExceptionnsae){thrownewInternalError("MD5notsupported",nsae);}byte[]md5Bytes=md.digest(name);md5Bytes[6]&=0x0f;/*clearversion*/md5Bytes[6]|=0x30;/*settoversion3*/md5Bytes[8]&=0x3f;/*clearvariant*/md5Bytes[8]|=0x80;/*settoIETFvariant*/returnnewUUID(md5Bytes);}v5 = SHA1(namespace)Version 4 (random)Javav4实现publicstaticUUIDrandomUUID(){SecureRandomng=Holder.numberGenerator;byte[]randomBytes=newbyte[16];ng.nextBytes(randomBytes);randomBytes[6]&=0x0f;/*clearversion*/randomBytes[6]|=0x40;/*settoversion4*/randomBytes[8]&=0x3f;/*clearvariant*/randomBytes[8]|=0x80;/*settoIETFvariant*/returnnewUUID(randomBytes);}Nil UUID00000000-0000-0000-0000-000000000000参考https://en.wikipedia.org/wiki/Universally_unique_identifierhttps://www.ietf.org/rfc/rfc4122.txthttps://stackoverflow.com/questions/13070674/get-the-unix-timestamp-from-uuid-version-1https://python.iitter.com/other/194094.html
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 12:59 , Processed in 0.818183 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表