UUID(Universally Unique IDentifier)是一个128位数字的唯一标识。RFC 4122描述了具体的规范实现。本文尝试从它的结构一步步分析为什么它能做到唯一性?及各个版本的使用场景。

Format

UUID使用16进制表示,共有36个字符(32个字母数字+4个连接符"-"),格式为8-4-4-4-12,如:

6d25a684-9558-11e9-aa94-efccd7a0659b
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
M中使用4位来表示UUID的版本,N中使用1-3位表示不同的variant。如上面所示:M =1, N = a表示此UUID为version-1,variant-1的UUID(Time-based ECE/RFC 4122 UUID)。

但是为什么最开始说它是一个128位的唯一标识呢?这里明明字母位数是(8+4+4+4+12)*8=256位。

因为上面的字母是用的16进制,一个16进制只代表4个bit,所以应该是(8+4+4+4+12)*4=128位。

UUID使用的是大数位format(big-endian),比如:

00112233-4455-6677-8899-aabbccddeeff 编码就是 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff.

UUID现有5种版本,是根据不同的使用场景划分的,而不是根据精度,所以Version5并不会比Version1精度高,在精度上,大家都能保证唯一性,重复的概率近乎于0。

Version1(date-time MAC address)

基于时间戳及MAC地址的UUID实现。它包括了48位的MAC地址和60位的时间戳,

接下来使用ossp-uuid命令行创建5个UUID v1。(在Mac安装brew install ossp-uuid)

uuid -n 5 -v1
5b01c826-9561-11e9-9659-cb41250df352
5b01cc7c-9561-11e9-965a-57ad522dee7f
5b01cea2-9561-11e9-965b-a3d050dd0f99
5b01cf60-9561-11e9-965c-1b66505f58da
5b01d118-9561-11e9-965d-97354eb9e996

肉眼一看,有一种所有的UUID都很相似的感觉,几乎就要重复了!怎么回事?

其实v1为了保证唯一性,当时间精度不够时,会使用13~14位的clock sequence来扩展时间戳,比如:

当UUID的生产成速率太快,超过了系统时间的精度。时间戳的低位部分会每增加一个UUID就+1的操作来模拟更高精度的时间戳,换句话说,就是当系统时间精度无会区分2个UUID的时间先后时,为了保证唯一性,会在其中一个UUID上+1。所以UUID重复的概率几乎为0,时间戳加扩展的clock sequence一共有74bits,(2的74次方,约为1.8后面加22个零),即在每个节点下,每秒可产生1630亿不重复的UUID(因为只精确到了秒,不再是74位,所以换算了一下)。

相对于其它版本,v1还加入48位的MAC地址,这依赖于网卡供应商能提供唯一的MAC地址,同时也可能通过它反查到对应的MAC地址。Melissa病毒就是这样做到的。

Version2(date-time Mac address)

这是最神秘的版本,RFC没有提供具体的实现细节,以至于大部分的UUID库都没有实现它,只在特定的场景(DCE security)才会用到。所以绝大数情况,我们也不会碰到它。

Version3,5(namespace name-based)

V3和V5都是通过hash namespace的标识符和名称生成的。V3使用MD5作为hash函数,V5则使用SHA-1。

因为里面没有不确定的部分,所以当namespace与输入参数确定时,得到的UUID都是确定唯一的。比如:

uuid -n 3 -v3 ns:URL http://www.baidu.com
2f67490d-55a4-395e-b540-457195f7aa95
2f67490d-55a4-395e-b540-457195f7aa95
2f67490d-55a4-395e-b540-457195f7aa95
可以看到这3个UUID都是一样的。

具体的流程就是

把namespace和输入参数拼接在一起,如"http/http://wwwbaidu.com" ++ “/query=uuid”;
使用MD5算法对拼接后的字串进行hash,截断为128位;
把UUID的Version和variant字段都替换成固定的;
如果需要to_string,需要转为16进制和加上连接符"-"。
把V3的hash算法由MD5换成SHA-1就成了V5。

Version4(random)

这个版本使用最为广泛:

uuid -n 5 -v4
a3535b78-69dd-4a9e-9a79-57e2ea28981b
a9ba3122-d89b-4855-85f1-92a018e5c457
7c59d031-a143-4676-a8ce-1b24200ab463
533831da-eab4-4c7d-a3f6-1e2da5a4c9a0
def539e8-d298-4575-b769-b55d7637b51e

其中4位代表版本,2-3位代表variant。余下的122-121位都是全部随机的。即有2的122次方(5.3后面36个0)个UUID。一个标准实现的UUID库在生成了2.71万亿个UUID会产生重复UUID的可能性也只有50%的概率

这相当于每秒产生10亿的UUID,持续85年,而把这些UUID都存入文件,每个UUID占16bytes,总需要45 EB(exabytes),比目前最大的数据库(PB)还要大很多倍。

Summary

如果只是需要生成一个唯一ID,你可以使用V1或V4。

  • V1基于时间戳和Mac地址,这些ID有一定的规律(你给出一个,是有可能被猜出来下一个是多少的),而且会暴露你的Mac地址。

  • V4是完全随机(伪)的。
    如果对于相同的参数需要输出相同的UUID,你可以使用V3或V5。

  • V3基于MD5 hash算法,如果需要考虑与其它系统的兼容性的话,就用它,因为它出来得早,大概率大家都是用它的。

  • V5基于SHA-1 hash算法,这个是首选。

UUID 全世界的唯一id!(唯一的接口标识符)相关推荐

  1. Android Q 获取设备唯一ID(UDID\GUID\UUID\SSAID\GAID)

    Android Q获取设备唯一ID(UDID\GUID\UUID\SSAID\GAID) 一.简介 1.1 问题背景 1.2 关键技术 二.解决方案 2.1 谷歌官方推荐方案 (4种) 2.2 实现方 ...

  2. 10.算法进阶之分布式篇——分布式环境下如何生成唯一ID——UUID

    UUID--全局唯一ID--universally unique identifie. 一般来说常用的基于时间进行排序,因为时间是自然递增的.但是全局唯一ID的两个核心要求是: 全局唯一 粗略有序 在 ...

  3. JS生成唯一id方式介绍(UUID和NanoID)

    记录下JS生成唯一id的方法. 1.生成uuid的方法 方法一: function guid() {return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.repl ...

  4. java获取imei_Android10 获取IMEI,获取UUID,唯一ID

    Andorid10无法获取IMEI,读写文件也被限制. 获取设备唯一ID逻辑. 如果Android10以上 -> 在设备的外部目录创建UUID,只要用户没有手动删除该文件UUID一直存在. 如果 ...

  5. 通用唯一识别码(uuid):吃透id随便搞

    Index v4 高64位 mostSigBits 低64位 leastSigBits v3 高64位 mostSigBits 低64位 leastSigBits v1 高64位 mostSigBit ...

  6. Java分布式唯一ID生成方案——比UUID效率更高的生成id工具类

    package com.xinyartech.erp.core.util;import java.lang.management.ManagementFactory; import java.net. ...

  7. 全局唯一ID发号器的几个思路

    标识(ID / Identifier)是无处不在的,生成标识的主体是人,那么它就是一个命名过程,如果是计算机,那么它就是一个生成过程.如何保证分布式系统下,并行生成标识的唯一与标识的命名空间有着密不可 ...

  8. Redis之String应用场景与SpringCache--存储对象信息、分布式唯一ID、文章阅读量、Lua脚本

    String应用场景 一.存储对象信息 代码 重写Redis序列 解决方式 剖析SpringCache常用注解 @CacheConfig @Cacheable @CachePut @CacheEvic ...

  9. 一线大厂的分布式唯一ID生成方案是什么样的?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 一.前言 分布式系统中我们会对一些数据量大的业务进行分拆,如:用户 ...

最新文章

  1. pandas中align函数的使用示例
  2. Unet论文解读代码解读
  3. liux 常用操作命令
  4. 如何将索引碎片数量降至最低
  5. zuc算法代码详解_最短路算法-dijkstra代码与案例详解
  6. 《电子元器件的可靠性》——3.7节电子元器件失效率鉴定试验
  7. (考勤记录导出教程)指纹考勤机科密C21
  8. 互联网知识变现,不起眼利润高的冷门行业有哪些?
  9. 关于小米驱动程序的问题
  10. Leetcode刷题100天—347. 前 K 个高频元素(优先队列)—day16
  11. 记录微信分享图标不显示的问题
  12. 《愤怒的小鸟2》上线华为应用市场;罗克韦尔自动化将以22.2亿美元收购Plex;优克联与伦敦合作伙伴签署分销协议 | 全球TMT...
  13. 使用牛顿迭代法求根 一元三次方程的根
  14. 初学开关电源设计全过程笔记
  15. 痛与快乐有一个代码是什么_痛苦与快乐
  16. 希腊字母常用指代意义及其中英文读音
  17. 【必拿下系列】106. 从中序与后序遍历序列构造二叉树105从前序与中序遍历序列构造二叉树
  18. python 保障系统(一)
  19. 【外汇天眼】MT4 vs MT5:哪个更适合外汇初学者
  20. 怎么在mac下运行映像dmg_Mac制作dmg镜像重新安装系统方法

热门文章

  1. sqlbench:一个测量和比较 SQL 语句执行效率的工具
  2. UVCCamera实现USB摄像头Android的APP
  3. qq撤回的信息腾讯服务器有吗,腾讯官方:撤回消息为何提示对方?丨QQ新增自定义撤回消息~...
  4. 省选专练川渝友谊考试S10礼物gift
  5. 【SVM回归预测】基于matlab粒子群算法优化SVM回归预测【含Matlab源码 1424期】
  6. Linux中tail与cat的区别
  7. python 化学工程_学化工的出路在哪儿?
  8. 牛刀小试(四)——较完善的购物系统
  9. 由于内存不够导致clickhouse节点无法启动
  10. RAM与ROM程序执行速度