Index

  • v4
    • 高64位 mostSigBits
    • 低64位 leastSigBits
  • v3
    • 高64位 mostSigBits
    • 低64位 leastSigBits
  • v1
    • 高64位 mostSigBits
    • 低64位 leastSigBits
  • UUIDv1(Java)

通用唯一识别码(uuid)是一种用于在计算机系统中标识信息的标识符,具有全局唯一性。

v4

在单体服务中,如果想生成全局唯一id,用于标识不同用户的会话、标识不同客户端可以使用UUIDv4。

UUIDv4是一种完全随机的UUID,它的生成方式不依赖于时间戳和节点ID,而是使用随机数生成。

SecureRandom是Java提供的用于生成随机数的安全随机数生成器,可以生成高质量的随机数,用于密码学、安全通信等领域。UUIDv4中使用的随机数就是SecureRandom提供的(byte[0-15])。

高64位 mostSigBits

UUIDv4的高64位(mostSigBits)是生成随机数的低位(byte[0-7])。其中有效位第7到12位为4,表示UUIDv4的版本号为4。

低64位 leastSigBits

UUIDv4低64位(leastSigBits)是生成随机数的高位(byte[8-15])。其中有效位第62到64位为1,表示UUID的IETF变体号。

v3

UUIDv3是一种基于命名空间和名称生成的UUID,它的生成方式需要提供一个命名空间和一个名称的组合。UUIDv3可以用于标识特定的对象或实体,例如URL、DNS、OID等

MD5(Message Digest Algorithm 5)是一种哈希算法,用于将任意长度的消息转换为固定长度的消息摘要(digest),通常为128位。

MD5算法的核心思想是将输入的消息分成若干个512位的消息块,然后对每个消息块进行一系列的位运算和移位操作,最终得到一个128位的消息摘要。UUIDv3使用的正是MD5的信息摘要(byte[0-15])。

高64位 mostSigBits

UUIDv3的高64位(mostSigBits)是消息摘要的低位(byte[0-7])。其中有效位第7到12位为3,表示UUIDv4的版本号为3。

低64位 leastSigBits

UUIDv3低64位(leastSigBits)是生成随机数的高位(byte[8-15])。其中有效位第62到64位为1,表示UUID的IETF变体号。

v1

UUIDv1的生成方式依赖于系统时钟和节点ID,用于分布式系统中的唯一性。UUIDv1是一种基于时间戳和节点ID生成的UUID,它的前8位包含时间戳信息,中间的4位包含版本号信息,后面的6位包含节点ID信息。

按照java.util.UUID的注释,画了下UUID的格式图。

/**
* The most significant long consists of the following unsigned fields:
* <pre>
* 0xFFFFFFFF00000000 time_low
* 0x00000000FFFF0000 time_mid
* 0x000000000000F000 version
* 0x0000000000000FFF time_hi
* </pre>
* The least significant long consists of the following unsigned fields:
* <pre>
* 0xC000000000000000 variant
* 0x3FFF000000000000 clock_seq
* 0x0000FFFFFFFFFFFF node
* </pre>
*/
#mermaid-svg-OOlMUBgPUPYBdsaM {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-OOlMUBgPUPYBdsaM .error-icon{fill:#552222;}#mermaid-svg-OOlMUBgPUPYBdsaM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OOlMUBgPUPYBdsaM .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-OOlMUBgPUPYBdsaM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OOlMUBgPUPYBdsaM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OOlMUBgPUPYBdsaM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OOlMUBgPUPYBdsaM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OOlMUBgPUPYBdsaM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OOlMUBgPUPYBdsaM .marker.cross{stroke:#333333;}#mermaid-svg-OOlMUBgPUPYBdsaM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OOlMUBgPUPYBdsaM .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-OOlMUBgPUPYBdsaM .cluster-label text{fill:#333;}#mermaid-svg-OOlMUBgPUPYBdsaM .cluster-label span{color:#333;}#mermaid-svg-OOlMUBgPUPYBdsaM .label text,#mermaid-svg-OOlMUBgPUPYBdsaM span{fill:#333;color:#333;}#mermaid-svg-OOlMUBgPUPYBdsaM .node rect,#mermaid-svg-OOlMUBgPUPYBdsaM .node circle,#mermaid-svg-OOlMUBgPUPYBdsaM .node ellipse,#mermaid-svg-OOlMUBgPUPYBdsaM .node polygon,#mermaid-svg-OOlMUBgPUPYBdsaM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OOlMUBgPUPYBdsaM .node .label{text-align:center;}#mermaid-svg-OOlMUBgPUPYBdsaM .node.clickable{cursor:pointer;}#mermaid-svg-OOlMUBgPUPYBdsaM .arrowheadPath{fill:#333333;}#mermaid-svg-OOlMUBgPUPYBdsaM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OOlMUBgPUPYBdsaM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OOlMUBgPUPYBdsaM .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-OOlMUBgPUPYBdsaM .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-OOlMUBgPUPYBdsaM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OOlMUBgPUPYBdsaM .cluster text{fill:#333;}#mermaid-svg-OOlMUBgPUPYBdsaM .cluster span{color:#333;}#mermaid-svg-OOlMUBgPUPYBdsaM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OOlMUBgPUPYBdsaM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

时间戳低位
时间戳中位
uuid版本号
时间戳高位
保留位
时钟序列
全局MAC地址_用户定义

高64位 mostSigBits

时间戳表示自UTC时间(协调世界时)的格林威治时间1970年1月1日00:00:00以来的秒数。
System.currentTimeMillis()方法获取当前时间的时间戳,除了System.currentTimeMillis()方法外,Instant.now().toEpochMilli()也可以获取时间毫秒戳。UUID的前32位包含了时间戳的低32位。UUID的32-48位包含了时间戳的中间16位。UUID的52-64位包含了时间戳的高12位。版本号位于时间戳中间的48-52位。

UUID中时间戳分散存储于各个位之中,这样做出来的哈希值更加离散。但是在底层有序的数据结构的数据库中,过于离散会导致索引树的频繁重建,MySQL中UUID生成函数提供swap_flag,如果swap_flag为1,时间低和时间高的部分(分别是第一组和第三组十六进制数字)被交换。如果结果存储在有索引的列中,这样可以将变化较快的部分移到右边,可以提高索引的效率。

低64位 leastSigBits

和v3和v4一样,变体有效位在第62到64位中,此时按照不同变体填入即可。

时钟回退问题是指系统时钟在某些情况下可能会向后调整,导致生成的UUID时间戳出现重复或者不连续的情况。UUIDv1中引入了时钟序列号,用于在时钟回退时产生不同的UUID。UUIDv1中的时钟序列号被存储在UUID的中间14位,可以保证在时钟回退时能够正确地生成不同的UUID,并且不会影响UUID的唯一性和随机性。

UUIDv1中的节点ID是一个48位的数字,用于标识生成UUID的节点。在UUIDv1中,节点ID的生成方法可以是MAC地址或者其他的硬件标识符,也可以是随机生成的数字。

UUIDv1(Java)

UUIDv1中包含了节点ID等信息,如果节点ID使用MAC地址,可能会泄露MAC地址,从而导致安全问题导致Java标准库没有提供UUIDv1的实现。

如果有特殊的需求,也可以自己实现UUIDv1生成算法。但是需要注意,在使用UUIDv1时,需要考虑到节点ID的唯一性和隐私问题,以及时钟序回拨的安全问题。

接下来,实现一个UUID生成算法类UUIDv1,其中包含了四个静态变量。lastTimestamp,记录上一个UUIDv1生成的时间戳,初始值为-1L,表示还没有生成过UUIDv1。nodeSequence,序列号,初始值为0L,每次生成UUIDv1时会自增1,用于并发不安全的可能产生的情况。clockSequence,时钟序列号,初始值为1L,用于在时钟回退时产生不同的UUIDv1,14位循环使用,回退时间间隔内最大支持14次的回退。sequenceMask,序列号掩码,用于限制序列号的范围在32位以内。

class UUIDv1 {private static long lastTimestamp = -1L;private static long clockSequence = 1L;private static long nodeSequence = 0L;private static long sequenceMask = -1L ^ (-1L << 32); // 32
}

leastSigBits是一个64位的数值,用于存储UUIDv1的低64位,其中包含了时间戳、时钟序列号和节点ID等信息。第1-2位变体保留位,不涉及为0跳过,第3位到第16位是时钟序列号,占用14位,如果当前时间戳小于上一个UUIDv1生成的时间戳(即时钟回退),则需要循环左移更新时钟序列号,防止生成重复的UUIDv1。最后生成节点ID和序列号,占用48位,其中高16位是节点ID,低32位是序列号,用于标识生成UUIDv1的节点和序列号。

节点ID和序列号的算法,首先定义一个node变量,用于存储节点ID的值,可以根据实际情况进行选择分布式的框架获取如zk。如果当前时间戳等于上一个UUIDv1生成的时间戳,说明需要生成不同的UUIDv1序列号,因此将nodeSequence自增1,并使用sequenceMask进行限制,保证序列号的范围在32位以内。如果nodeSequence的值为0,说明序列号已经达到最大值,需要等待下一个时间戳的到来,调用tilNextMillis()函数等待。如果当前时间戳不等于上一个UUIDv1生成的时间戳,说明进入到下一秒或者已经发生时钟回退需要重新生成序列号,将nodeSequence重置为0。最后更新lastTimestamp的值为当前时间戳,返回node和nodeSequence的值。

class UUIDv1 {private static long lastTimestamp = -1L;private static long clockSequence = 1L;private static long nodeSequence = 0L;private static long sequenceMask = -1L ^ (-1L << 32);public static UUID timeUUIDFromNode(long node) {long timestamp = Instant.now().toEpochMilli();long leastSigBits = 0L | 0L| (timestamp < lastTimestamp // clock backwards? (clockSequence = ((clockSequence << 1) & 0x3FFFL) | ((clockSequence >>> (14 - 1)) & 0x3FFFL)): clockSequence) << 48| nodeseq(node, timestamp);return null;}private static synchronized long nodeseq(long node, long timestamp) {if (lastTimestamp == timestamp) {nodeSequence = (nodeSequence + 1) & sequenceMask;if (nodeSequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {nodeSequence = 0;}lastTimestamp = timestamp;return node << 32 | nodeSequence;}private static long tilNextMillis(long lastTimestamp) {var timestamp = Instant.now().toEpochMilli();while (timestamp <= lastTimestamp) {timestamp = Instant.now().toEpochMilli();}return timestamp;}
}

mostSigBits是一个64位的数值,用于存储UUIDv1的高64位,其中包含了时间戳和版本号等信息。前32位是时间戳的低32位。接下来16位是时间戳的中间16位。接下来4位是版本号,固定为0001,表示UUIDv1版本。最后12位是时间戳的高12位,用于标识UUIDv1生成的时间戳。

public static UUID timeUUIDFromNode(long node) {long timestamp = Instant.now().toEpochMilli();long leastSigBits = 0L | 0L| (timestamp < lastTimestamp // clock backwards? (clockSequence = ((clockSequence << 1) & 0x3FFFL) | ((clockSequence >>> (14 - 1)) & 0x3FFFL)): clockSequence) << 48| nodeseq(node, timestamp);long mostSigBits = 0L | (lastTimestamp << 32) | ((lastTimestamp & 0xFFFF00000000L) >> 16)| 0x1000L | ((lastTimestamp >> 48) & 0x0FFF);return new UUID(mostSigBits, leastSigBits);
}

最后需要将mostSigBits和leastSigBits部分合并,生成完整的UUIDv1,完整算法。

class UUIDv1 {private static long lastTimestamp = -1L;private static long clockSequence = 1L;private static long nodeSequence = 0L;private static long sequenceMask = -1L ^ (-1L << 32);public static UUID timeUUIDFromNode(long node) {long timestamp = Instant.now().toEpochMilli();long leastSigBits = 0L | 0L| (timestamp < lastTimestamp // clock backwards? (clockSequence = ((clockSequence << 1) & 0x3FFFL) | ((clockSequence >>> (14 - 1)) & 0x3FFFL)): clockSequence) << 48| nodeseq(node, timestamp);long mostSigBits = 0L | (lastTimestamp << 32) | ((lastTimestamp & 0xFFFF00000000L) >> 16)| 0x1000L | ((lastTimestamp >> 48) & 0x0FFF);return new UUID(mostSigBits, leastSigBits);}private static synchronized long nodeseq(long node, long timestamp) {if (lastTimestamp == timestamp) {nodeSequence = (nodeSequence + 1) & sequenceMask;if (nodeSequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {nodeSequence = 0;}lastTimestamp = timestamp;return node << 32 | nodeSequence;}private static long tilNextMillis(long lastTimestamp) {var timestamp = Instant.now().toEpochMilli();while (timestamp <= lastTimestamp) {timestamp = Instant.now().toEpochMilli();}return timestamp;}
}

通用唯一识别码(uuid):吃透id随便搞相关推荐

  1. 云客Drupal源码分析之通用唯一识别码UUID

    先来看一个问题:假设一个网络系统每秒钟需要保存数十万来自用户提交的信息,并分配一个id给每条信息用于以后唯一标识它,那么怎么产生这个id呢?不能重复又要足够快以支持高并发,有这么强大的单台服务器吗?即 ...

  2. 通用唯一识别码UUID

    UUID是通用唯一识别码(Universally Unique Identifier)的缩写.UUID 的目的,是让分布式系统中的所有元素,都能有唯一的辨识资讯,而不需要透过中央控制端来做辨识资讯的指 ...

  3. 用于分布式系统的ID?——UUID(Universally Unique Identifier,通用唯一识别码)

    用于分布式系统的ID?--UUID(Universally Unique Identifier,通用唯一识别码) UUID 是 通用唯一识别码(Universally Unique Identifie ...

  4. java生成UUID通用唯一识别码

    一.UUID概述 UUID含义是通用唯一识别码 (Universally Unique Identifier),这是一个软件建构的标准,也是被开源软件基金会 (Open Software Founda ...

  5. UUID - 通用唯一识别码

    UUID - 通用唯一识别码 通用唯一识别码(英语:Universally Unique Identifier,UUID),是用于计算机体系中以识别信息数目的一个 128 位标识符,还有相关的术语:全 ...

  6. UUID 通用唯一识别码(Universally Unique Identifier)介绍

    UUID 简介 UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部分.其目的,是让 ...

  7. uuid通用唯一识别码

    https://www.npmjs.com/package/uuid 1.安装 npm install uuid 2.使用 import { v4 as uuid } from 'uuid'; uui ...

  8. 蓝牙 16 位通用唯一标识符 (UUID)

    https://www.bluetooth.com/specifications/assigned-numbers/ 16 位的通用唯一标识符 (UUID)分类 分配类型 分配UUID段 作用 GAT ...

  9. python函数的唯一标识_python基础教程Python通用唯一标识符uuid模块使用案例

    1. 背景知识: UUID: 通用唯一标识符 ( Universally Unique Identifier ), 对于所有的UUID它可以保证在空间和时间上的唯一性. 它是通过MAC地址, 时间戳, ...

最新文章

  1. SpringMVC-RestfulCRUD || 员工信息表增删改查操作的具体实现
  2. php 获得当月时间戳,php获取当前月与上个月月初及月末时间戳的方法
  3. LiveVideoStackCon讲师热身分享 ( 九 ) —— 51Talk音视频技术思考及非典型挑战
  4. pandas 每一列相加_Python数据分析——Pandas 教程(上)
  5. RAPID 信号的互锁和同步 WaitTestAndSet 和 TestAndSet
  6. linux中查找文件属于那个软件包的方法
  7. Python 俄罗斯方块, 基于pyqt5实现俄罗斯方块 --pyqt5 进阶
  8. Velocity中避免null引起的数据问题
  9. 一步一步安装Git控件版本工具
  10. Android:模拟器使用命令安装apk
  11. 是的,我开通了小密圈
  12. 清除img和文字间的空隙【vertical-align的用途】
  13. 地图之美(地图制图)
  14. Editplus激活码
  15. html中span怎么写,html的span标签怎么使用
  16. wordpress企业网站模板
  17. GitHub简介、fork、pull和clone、快速起步
  18. 网易云信 UI 开发
  19. socket通信函数
  20. 开车,开车,裤子里穿丝袜是什么感觉?

热门文章

  1. 【软件工程】软件工程基础知识
  2. 网页显示正在加载安全连接服务器,chrome内核的浏览器 打开网页巨慢 “正在建立安全连接” 解决方案...
  3. java计算机毕业设计迎宾酒店管理系统录屏源程序+mysql+系统+lw文档+远程调试
  4. T总线槽计算机知识,综合布线知识点试题lpar;答案rpar;
  5. 面试官问怎么进行代码优化,我一口气讲了11个重点
  6. Android短视频app开发中如何实现上下滑动切换效果
  7. Slot计算资源管理
  8. 最浅显易懂的约瑟夫环讲解
  9. bilibili老版本_【图片】【发布】哔哩哔哩bilibili替换旧版播放(稍后再看)_bilibili吧_百度贴吧...
  10. java计算机毕业设计汽车租赁系统演示录像源码+程序+lw文档+mysql数据库