Command Palette

Search for a command to run...

UUID 生成器:v1、v4、v7 解释(以及实际使用哪个)

UUID 生成器:v1、v4、v7 解释(以及实际使用哪个)

T
Toolz Team
|Jul 1, 2026|16 最小读数

其他工具 合集的一部分

UUID第一次对我来说真的很重要,我正在将一个与WordPress相邻的SaaS从一个单一的MySQL盒子转移到一个具有读取副本的设置,并计划稍后分片。自动增量ID已经好几年了 - 直到两个服务开始插入到将变成同一逻辑表中,然后突然 id = 42 意两行不同。那's自动增量悄然停止工作的那一刻,而UUID是通常的答案。

UUID是一个128位的值,你可以在任何机器上,在任何时间,没有协调,仍然相信是独一无二的。那个"没有协调"部分是全部:一个飞机上的离线移动应用程序,三个微服务,一个后台工作人员可以同时铸造ID,永远不会碰撞。那种自信的数学支持真是荒谬,而I'一秒钟就会向你展示多么荒谬。

用户识别器 on toolz。dev 立即创建多个版本的单个或批量 UUID,就在您的浏览器中 - 当您're播种表格或需要一次性 ID 进行测试时非常方便。本指南涵盖了版本的实际含义,2026 年要选择哪个版本,如何在不破坏数据库索引的情况下存储它们,以及我犯的错误,以便您可以跳过它们。

TL;博士: 2026年新的数据库主键,生成 UUID v7- it's时间排序所以索引很好,它没有't泄漏硬件像v1。使用 v4 当你想要纯粹的不可预测性时。将它们存储为本地人 uuid 类型或 BINARY(16),从来没有 VARCHAR(36)。使它们与 用户识别器并且将其与 时间戳转换器 阅读烘烤成 v7 的时间。所有客户端,全部免费。


什么是 UUID,到底是什么?

UUID(通用唯一标识符)是一个128位的数字,用于识别没有中央机构分发ID的东西,微软称同一个东西为GUID(全球唯一标识符);它们'在重要的每一个方面都是相同的规范文本形式是36个字符-32个十六进制数字分成五个连字符组8-4-4-4-12:

550e8400-e29b-41d4-a716-446655440000

其中两个十六进制位置是't随机数据-它们're元数据。第 13 个十六进制数字编码 版本 (哪一个生成策略使它),而第四组的第一位数字编码为 变体 (遵循哪种布局标准) 89a、或者 b 为(标准 UUID)。所以在上面的例子中, 4 在第三组中告诉你's a v4。

"独一无二,"到底有多独特?

V4 UUID在保留版本和变体位之后,有122个随机位。那's 2^122个可能的值,或大约5.3 十亿:

5,316,911,983,139,663,491,615,228,241,121,400,000

为了具体化这一点:如果你每秒产生 10 亿个 UUID,你'd 大约需要 86 年才能达到 50% 的可能性 单身 collision anywhere。在实际工程术语中,v4碰撞不会发生,你可以设计得好像永远不会。


UUID v1、v4 和 v7 之间的区别是什么's?

规格 - 最初 RFC 4122,现已更新 RFC 9562 (2024)- 定义了几个版本。三件事日常工作。

UUID v1 - 时间戳 + MAC 地址

v1 缝合在一起一个 100 纳秒的时间戳(从 1582 年 10 月 15 日算起,公历开始的日期 - 我最喜欢的规格琐事之一),网卡's MAC 地址。它's 自然时间排序,您可以从中提取创建时间。

问题就在定义中:它嵌入了制造它的机器的 MAC 地址。这会泄露硬件身份,并结合时间戳,使 ID 有点可预测。示例: 6ba7b810-9dad-11d1-80b4-00c04fd430c8。I'd现在只使用v1进行遗留兼容。

UUID v4 - 随机

v4是122位随机性,没有别的,it's版本大多数人说"UUID,"和it's死简单:没有时间戳,没有硬件,没有订单示例: f47ac10b-58cc-4372-a567-0e02b2c3d479

1000万彩票网 好的地方是它什么都不会泄露,也无法预测,这正是你想要的任何应该't可以猜测的东西,缺点是它's 随机因此,连续插入会分散在您的索引中 - 正如我所发现的那样,该索引具有实际的规模性能成本。

UUID v7 - 时间排序 + 随机

v7 是现代的折衷方案,在 RFC 9562 中标准化,前 48 位是以毫秒为单位的 Unix 时间戳;其余是随机的 示例: 018e4880-d4d0-7b9c-8c37-2a5c0f1e3d8a

That layout means v7 IDs sort chronologically - new rows land at the "end" of a B-tree index 而不是 scattering - while still be globally unique and coordination-free。it leaks improjects time (usually fine) but not hardware。对于新项目,这是我默认的主键,它's the 方向 IETF now points too。

Here's一眼的权衡:

版本 订购? 泄漏 最好的
v1 是(时间) MAC地址 + 时间 仅限旧系统
v4 否(随机) 没什么 不可猜测的代币,一般 ID
v7 是(时间) 大约创建时间 新的数据库主键

较少使用的版本也存在:v3 和 v5 是命名空间加名称的确定性哈希值(v5 使用 SHA-1,优于 v3's MD5),v6 是重新排序的 v1,v8 保留用于自定义实现。


您应该使用 UUID 或自动增量 ID 吗?

I've在设计评论中的争论比其他任何评论都多,所以这里's是我实际使用的框架,而不是宗教答案。

坚持自动增量时 您拥有单一数据库,性能和存储都很紧张,人类需要读取 ID。一个整数是 4.8 字节,而一个 UUID's 16,整数比较更快,并且 "order #12345"比一个 36 个字符的 UUID 更容易读取手机。在没有分片的单个盒子上,自动递增确实是更简单、更快的选择 - don't 触及超时 UUID。

切换到 UUID 时 re分布式(多个服务或服务器独立铸造id),you're担心枚举(自动增量id可猜测,悄悄透露你的记录计数- /users/1234 告(你拥有的用户少于1235个)攻击者,你需要合并来自多个数据库的数据而不会发生冲突,或者你希望客户端在同步之前生成ID。那个枚举点是真正的安全考虑,人们低估了这一点。

以及v7中间立场: UUID v7 为您提供分布式生成 UUID 自动增量的指数友好排序,不泄露记录计数 对于2026年大多数需要非顺序id的新项目,v7是结束争论的答案。


如何在不破坏索引的情况下存储 UUID?

这是我自己犯的昂贵错误所产生的部分,所以如果没有其他地方,请注意这里。

关于我提到的那个迁移,我将新的 UUID 存储为 VARCHAR(36) 因为这是显而易见的、可读的事情。它有效 - 然后表增长,插入和连接变得明显更慢。两个问题变得更加复杂:我每个 ID 花费 36 字节而不是 16, 我使用的是随机 v4 UUID,因此每个插入都落在主键索引中的随机点,将其分割并鞭打缓冲池。修复程序是将它们存储为二进制,并且在下一个项目中,切换到 v7,因此插入保持顺序。

PostgreSQL 有本地人 uuid type - 使用它, 它存储16字节, 比较快:

CREATE EXTENSION IF NOT EXISTS "pgcrypto";

CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

我的SQL 没有原生 UUID 类型,因此商店 BINARY(16) 并转换为 UUID_TO_BIN() / BIN_TO_UUID().第二个论点很重要:

CREATE TABLE users (
    id BINARY(16) PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- The `true` swaps the timestamp bytes for better index locality on v1
INSERT INTO users (id, name, email)
VALUES (UUID_TO_BIN(UUID(), true), 'Alice', '[email protected]');

SELECT BIN_TO_UUID(id, true) AS id, name, email FROM users;

要记住的规则:本地人 uuid 输入您拥有一个的地方, BINARY(16) 你不在哪里't,以及 VARCHAR(36) 基本上永远不会因为某个关键而你'll索引并加入。


如何在代码中生成 UUID?

对于快速的一次性, 用户识别器 比打开 REPL 更快。在代码中,每种主要语言都内置了这个或一步之遥。

JavaScript/TypeScript- 浏览器和节点现在都出货了 v4 生成器:

const id = crypto.randomUUID();   // v4, no dependency needed
// For v7, use the 'uuid' package:
import { v7 as uuidv7 } from 'uuid';
const ordered = uuidv7();

Python:

import uuid
uuid.uuid4()                                  # random
uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com') # deterministic (SHA-1)

爪哇: UUID.randomUUID() 开箱即用地为您提供 v4; v7 需要一个类似的库 java-uuid-generator 或者小型 RFC 9562 实现。

去: github.com/google/uuid 给你们两个- uuid.New() 为v4和 uuid.NewV7() 为v7。

请注意,本机运行时帮助程序几乎总是为您提供 v4。如果您特别想要 v7 进行订购,通常需要一个库,因为它's 是较新的标准,并非每个 stdlib 都赶上了。


UUID 实际上在真实系统中出现在哪里?

It's 抽象地容易谈论 UUID,所以这里是 I've 依赖的具体地方,因为你挑的版本确实取决于工作。

分布式设置中的数据库主键。 这是经典案例,也是为我开始这篇文章的案例,当不止一个作者可以插入到同一个逻辑表中 - 副本、分片或共享模式的两个服务 - 自动递增中断的那一刻,一个 v7 主键解决了协调问题,并且仍然可以干净地索引,因为它's 时间排序。

客户端生成的离线优先应用程序 ID。 Mobile app 或浏览器 SPA 常常需要创建一条记录,然后才能与服务器对话 - 想想写在平面上的注释,或者是即时显示新行的乐观 UI 如果客户端前面铸造一个 UUID,则记录从第一个击键开始具有稳定的身份,并在没有服务器往返的情况下同步到 " 获取 ID。" I've 使用它来使表单即使在片状连接上也能感觉即时。

URL 和 API 中的不可枚举的资源标识符。/orders/1042 URL里悄悄地告诉任何人你've最多有1042个订单,让他们走路 /orders/1041/orders/1040依此类推。在 UUID 中交换可以消除业务度量泄漏和易于枚举。对于用户在 URL 中看到的任何内容,这都值得这样做 - 尽管请记住,UUID 不是访问控制机制;背后仍然需要真正的授权检查。

用于追踪的相关 ID。 当单个请求在五个微服务中粉丝化时,将一个 UUID 作为相关 ID 并将其记录在每个跳转处 "这个混乱中的某个地方,某些东西失败了 " 进入所有日志上的单个可抓取字符串。这是一个即使是普通的 v4 也完美的地方 - 你不需要 't 需要排序,只是独特性。

幂等键。 Payment 和 webhook API 经常要求客户端发送一个 UUID 作为幂等密钥,这样重试的请求就不会't 向一张卡收费两次,客户端生成一次,重试时重用,服务器在上面去掉它's 一个小模式,可以防止非常昂贵的类错误。


常见问题

UUID 有何用途?

UUID唯一标识某物 - 数据库行,API资源,会话,上传文件,跨微服务的跟踪 - 无需中央服务来分发ID。It's 每当多个系统或客户端必须独立创建标识符并且仍然确保他们赢了时,首选't冲突。您可以立即生成一个与。 用户识别器 在工具z.dev上。

两个 UUID 可以相同吗?

理论上是的;实践中没有。 v4 UUID 有 122 个随机位,给出大约 5.3 个不亿万的可能性。您'd 需要生成大约 2.7 千万亿个 UUID,然后才能达到 50% 的几率,甚至一次碰撞。对于每个真正的工程目的,您可以将 UUID 视为保证唯一。

2026年该用哪个UUID版本?

对于新的数据库主键,UUID v7 - it's 有时间顺序,可在保持全局唯一性的同时进行高效索引,并且 it's RFC 9562 下的当前 IETF 推荐。当不可预测性很重要时使用 v4,例如标识符不得是可猜测的。避免使用 v1 进行新工作,因为它嵌入了生成机's MAC 地址。

UUID 是顺序的吗?

v1和v7是有时间顺序的,所以在较早的排序之后生成较晚排序的id;v4是完全随机的,没有顺序,顺序排序是v7对b树索引友好- 新行追加而不是散射的原因,如果你're在一个大表上使用随机v4作为主键,那么缺乏顺序会损害插入和索引性能。

我应该如何将 UUID 存储在数据库中?

使用本机 uuid 输入您的数据库是否有一个(postgresql 有)。否则存储 BINARY(16)在 MySQL 8.0+ 中转换为 UUID_TO_BIN()BIN_TO_UUID().避免 VARCHAR(36)CHAR(36) 对于键 - 字符串存储每行浪费 20 字节并减慢每次比较的速度,这在大表上加起来很快。

UUID 和 GUID 之间的区别是什么?

They're一样的东西,UUID是来自RFC 4122的术语,用于大多数语言和平台;GUID是微软'的名称,常见于Windows和。NET。的格式和保证是相同的,因此您可以互换对待GUID和UUID。

我可以从 UUID 中提取创建时间吗?

从 v1、v6 和 v7 开始,是的 - 他们对时间戳进行编码。 v7 在其前 48 位中存储毫秒 Unix 时间戳,您可以用它进行解码和读取 时间戳转换器。v4和v5不包含时间信息,因此那里's没有什么可以从中提取的。

UUID v4对于会话令牌来说足够安全吗?

Not on its own。v4's 122个随机位是不可预测的,但会话和身份验证令牌通常希望从加密安全的生成器中至少有256个位。使用专门构建的安全随机令牌进行auth,并保留UUID用于识别资源而不是保护资源。

如何生成 UUID?

用你的语言's内置生成器: crypto.randomUUID() 在现代浏览器和 Node。js 中, uuid.uuid4() 在 Python 中,或者 Guid.NewGuid() 在。NET 中,每个调用都产生一个 v4 UUID。对于快速的一次性或批量,请立即生成它们 用户识别器 在 toolz。dev 上 - 无需代码。

UUID 多少个字符?

UUID是36个字符在其规范的文本形式:32个十六进制数字加上将其分成8-4-4-4-12组的四个连字符,该文本编码128位,这就是为什么将其存储为16个原始字节的原因 BINARY(16) 36字的字串要紧凑得多。


包裹起来

UUID是你不具备的基础之一't思考直到一个系统成长到单个数据库之后- 然后他们're一切2026年简短版本:默认到 v7 对于新的主键,请使用 v4 当您需要不可猜测的 ID 时,请将它们存储为 土生土长的 uuidBINARY(16)并且跳过 v1 了解任何新内容。向我学习 VARCHAR(36) 下午所以你不'重复一遍。

免费立即生成它们 用户识别器 在toolz。dev上 - 单个或批量,任何版本,所有客户端,没有任何上传 当您需要读取v7内部的时间时,触及 时间戳转换器并且浏览其余部分 编码工具- 600 多个免费公用事业 - 结束 Toolz.dev

Frequently Asked Questions

A UUID uniquely identifies something — a database row, an API resource, a session, an uploaded file, a trace across microservices — without needing a central service to hand out IDs. It's the go-to whenever multiple systems or clients must create identifiers independently and still be sure they won't clash. You can generate one instantly with the UUID Generator on toolz.dev.

Comments

0 comments

0/2000 characters

No comments yet. Be the first to share your thoughts!