目录

UUID使用以及区别

UUID 的 8 个版本以及何时使用它们;能不能用UUID作为数据库主键

UUID的全称是Universally Unique Identifier,中文为通用唯一识别码。

在对 UUID 进行说明之前,我们来看一个标准的 UUID。

下面就是一个标准的 UUID,使用横杠分隔符来进行分隔:

./images/image-20260115205830070.png

  • 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 生成方法,如:

  • ULID:将基于时间戳的排序与随机性相结合,确保单调性。
  • Snowflake:由 Twitter 提出,包含时间戳、机器 ID 和序列号。
  • KSUID:为分布式系统优化的 K 排序唯一标识符。

虽然这些替代方案在特定情况下很有效,但 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 等,但它们都有范围限制,可能会用尽。

  • 性能问题: 在数据迁移期间,如果使用自增主键,数据库可能会产生额外的性能开销。这可能是由于重新计算主键值或更新相关索引所致。这可能会导致数据迁移过程变慢。