UUID:当自增不够时
为什么唯一标识符在分布式系统中至关重要?对比UUID与自增ID的优劣,了解v4和v7版本的区别,学习在数据库和API中正确使用UUID。
你的数据库使用自增ID。1, 2, 3, 4...简单。
然后你合并两个数据库。或在URL中暴露ID。或有人发现他们可以通过递增URL中的ID来猜测其他用户的数据。
顺序ID有问题。UUID解决其中一些。
什么是UUID?
通用唯一标识符。128位数字,通常显示为带破折号的32个十六进制字符:
550e8400-e29b-41d4-a716-446655440000
UUID生成背后的数学使碰撞在天文学上不太可能。你可以在不同机器上、不同时间生成UUID,无需协调,它们不会碰撞。
为什么不只用自增?
安全。 顺序ID泄露信息。如果你的用户ID是15847,攻击者知道至少有15846个其他用户。他们可以通过尝试顺序ID枚举资源。
分布式系统。 生成ID的多个服务器需要协调以避免重复。UUID不需要协调。
合并数据。 用顺序ID合并数据库是噩梦。UUID干净合并。
离线创建。 移动应用可以用UUID离线创建记录。不需要等待服务器分配的ID。
UUID版本
不是所有UUID都以相同方式创建。
版本1: 基于时间戳和MAC地址。唯一,但透露何时何地创建。
版本4: 随机。最常见。没有信息泄露。
版本7: 基于时间戳但可排序。新数据库从中受益。
对于大多数用途,版本4(随机)是正确选择。
权衡
UUID不是免费的。
大小。 128位vs整数的32位。更大的索引,更多存储。
可读性。 user/15比user/550e8400-e29b-41d4-a716-446655440000更容易记住。
性能。 随机UUID在某些数据库中导致索引碎片。UUID v7解决了这个问题。
调试。 在日志中搜索UUID与简单数字相比很繁琐。
何时使用什么
使用自增当:
- 仅内部,从不暴露给用户
- 简单应用,单个数据库
- 人类可读性很重要
使用UUID当:
- ID出现在URL或API中
- 多个系统创建记录
- 通过模糊性的安全有帮助
- 可能合并数据
实用技巧
不要在MySQL中将UUID用作主键。 改用它们作为辅助唯一列。MySQL的聚集索引在随机UUID下性能不佳。
考虑UUID v7。 如果你的数据库支持它,时间戳可排序的UUID给你两全其美。
URL中移除破折号。 550e8400e29b41d4a716446655440000仍然是有效的UUID,在URL中更短。
UUID解决顺序ID无法解决的实际问题。但它们并不总是正确选择。根据你的实际需求选择,而不是因为UUID听起来更专业。