UUID使用以及区别
UUID 的 8 个版本以及何时使用它们;能不能用UUID作为数据库主键
UUID的全称是Universally Unique Identifier,中文为通用唯一识别码。
在对 UUID 进行说明之前,我们来看一个标准的 UUID。
下面就是一个标准的 UUID,使用横杠分隔符来进行分隔:

- M 表示 UUID版本,目前只有五个版本,即只会出现1,2,3,4,5…
- 数字 N 的一至三个最高有效位表示 UUID 变体,目前只会出现 8,9,a,b 四种情况。
UUID V1 基于时间戳的 UUID
原理:timestamp + MAC 地址。
特点:具有时间顺序性,能确保全局唯一性。
安全性:由于使用了MAC地址,可能暴露设备信息,存在隐私风险。
适用场景:适用于需要时间顺序的场景,如日志记录等。
缺点:
- 机器的MAC地址出厂后不能保证完全唯一,且之后 MAC 地址也可手动修改
- MAC 地址的暴露会造成了隐私与安全问题
- 若一台机子上的两个进程同时跑,有可能出现重复问题
UUID V2 DCE(Distributed Computing Environment)安全的 UUID
原理:基于 v1 的基础上优化了下,更安全。
这个版本的 UUID 算法与V1版本的 UUID 相同,但会将时间戳的前 4 位替换为 POSIX 的 UID 或 GID。
安全性较高,但实际应用较少。
UUID V3 基于名称空间的 UUID(MD5)
原理:基于 namespace + 输入内容 进行 MD5。
特点:具有可重复性,相同命名空间和名称生成的UUID一致。
安全性:使用MD5算法,安全性较低。
适用场景:适用于需要确定性生成的场景,如命名空间下的唯一标识。
UUID V4 基于随机数的 UUID
原理:基于随机数。
这个版本的UUID是使用最多的。提供了简单性和隐私性,但代价是潜在的(尽管极不可能发生)碰撞。该版本被广泛应用于顺序排列并不重要的场合。
UUID V5 基于命名空间的UUID(SHA-1)
原理:跟 V3 差不多,只是把散列算法的 MD5 变成 SHA1。
确保相同输入的结果具有确定性
UUID V6 改进的时间序列UUID
v1 的重组版本,具有更强的私密性,并针对时间顺序排序进行了优化。
UUID V7 时间戳 + 随机数
旨在提供基于时间的顺序排序,是数据库索引和分布式系统的理想选择。
UUIDv7 解决了早期版本的主要缺陷,尤其是在数据库索引和分布式系统方面。通过使用有时间顺序的结构,可以确保:
- 高效索引:基于时间的顺序排列减少了数据库索引中的碎片,从而提高了查询性能。
- 高可扩展性:适用于需要唯一、有序标识符的分布式环境。
- 隐私性:避免包含 MAC 地址等敏感信息。
例如,生成 UUIDv7 需要将时间戳编码到标识符中,这样即使在分布式系统中也能确保有序。谷歌的 UUID 库等工具支持用各种编程语言生成 UUIDv7。
UUID V8 自定义UUID (尚未正式发布)
允许自定义应用特定元数据字段,提供无与伦比的灵活性。
UUIDv8 引入了一项突破性功能:针对特定应用需求的自定义位。该版本允许在 UUID 中直接嵌入元数据,使其具有很强的适应性:
- 物联网设备:嵌入设备特定信息
- 跨系统数据传输:包含上下文元数据,便于跟踪。
- 自定义应用:根据特定领域需求定制 UUID。
UUIDv8 的灵活性需要权衡利弊,如确保自定义字段在应用上下文中保持唯一性。随着采用率的提高,很可能会出现最佳实践和库来规范这些实施。
总结
比较 UUID 版本
| 版本 | 构造方式 | 主要功能 | 用例 |
|---|---|---|---|
| v1 | 时间 + MAC地址 | 高唯一性, 隐私问题 | 传统系统, 内部工具 |
| v4 | 随机 | 简单, 高隐私性 | Web应用, 通用功能 |
| v6 | 基于时间(重构的) | 有序, 隐私增强 | 现代数据库 |
| v7 | 时间有序(RFC 9562) | 索引优化 | 分布式系统, 日志 |
| v8 | 自定义字段 | 高灵活性 | IoT, 特定应用 |
超越 UUID:替代方案与灵感
UUIDv7 和 UUIDv8 的开发参考了其他 ID 生成方法,如:
虽然这些替代方案在特定情况下很有效,但 UUID 为大部分应用提供了标准化、跨平台的解决方案。
结论和建议
UUID 的发展反映了分布式系统日益增长的复杂性,以及对高效、安全和灵活的唯一标识符的需求。随着 UUIDv7 和 UUIDv8 等新版本的普及,开发人员应该:
- 选择正确的版本:使用 UUIDv7 满足有时间顺序的需求,使用 UUIDv8 满足自定义元数据的需求。
- 利用库:利用现有的库,确保符合 RFC 规范。
- 随时了解信息:监控 UUID 标准和库的更新,利用新功能。
通过了解和使用合适的 UUID 版本,从而确保系统的可扩展性、性能和安全性。
能不能使用UUID作为数据库主键?
可以使用UUID作为数据库主键,但需要考虑其优缺点和适用场景。
优点:
-
全局唯一性:UUID保证了在分布式系统中生成的ID不会重复,无需中央协调。
-
无需中心化生成:每个节点都可以独立生成,无需依赖中心服务器。
-
适合分布式系统:特别适用于多主数据库架构或需要离线操作的场景。
缺点:
- 性能影响:UUID是无序的,插入时可能导致索引分裂和重组,影响写入性能。 - 存储空间:UUID通常为128位(如UUIDv4),比整型ID占用更多存储空间。 索引效率:由于随机性,可能导致索引碎片化,影响查询性能。 推荐使用场景:
分布式系统:当系统分布在多个节点且需要避免ID冲突时。 多主数据库:在需要多个主数据库同时写入的场景中。 离线操作:当应用可能在离线状态下运行,需要生成唯一ID时。 最新建议: 目前推荐使用UUIDv7,它结合了时间戳和随机数,具有时间有序性,能较好地解决传统UUID的性能问题。
选择是否使用UUID作为主键,应根据具体业务需求、数据量大小和性能要求来决定。
自增ID 作为数据库id的好处与坏处
在 MySQL 中,可以通过设置 AUTO_INCREMENT 属性实现 ID 的自增长,通常用于作为主键 ID。
使用自增 ID 作为主键的好处包括:
-
存储空间节省:ID 为数字,占用的位数比 UUID 小得多,因此在存储空间上更加节省。
-
查询效率高:ID 递增,利于 B+Tree 索引的查询效率提高。
-
方便展示:ID 较短,方便在系统间或前台页面进行展示。
-
分页方便:ID 连续自增,有利于解决深度分页问题。
然而,使用自增主键也存在一些问题:
-
分库分表困难:在分库分表时,无法依赖单一表的自增主键,可能导致冲突问题。
-
可预测性:由于 ID 是顺序自增的,因此具有一定可预测性,存在一定的安全风险。
-
可能用尽:自增 ID 可能是 int、bigint 等,但它们都有范围限制,可能会用尽。
-
性能问题: 在数据迁移期间,如果使用自增主键,数据库可能会产生额外的性能开销。这可能是由于重新计算主键值或更新相关索引所致。这可能会导致数据迁移过程变慢。