UUID 讨论

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

那些熟悉数据库和持久性的人可能有过与我在过去几年中有过几次相同的讨论:

您使用数字或字符串值作为 UUID 吗?

在进行了大量分布式、多租户开发之后,我对此的立场非常明确:我更喜欢 String。或者更好地说,我更喜欢 UUID。

当然,id 为 345 的用户比 id 为 03a3a8b1-002c-4f7b-aefb-1691cc274718 的用户更容易记住,但是当您的 id 开始超过 10000 时,这个论点就消失了,在这种情况下,您将复制粘贴它们并最终得到与 UUID 相同的工作量。

UUID 真正开始派上用场的地方是当您开始跨服务器同步数据时。看,大多数依赖数字值作为 id 的系统都是使用自动生成的值来实现的。这意味着您无法控制将哪个 ID 分配给系统中的某个实体,因此使得跨服务器传输数据变得一团糟。

例如,假设您有一个 ID 为 3 的实体 A 和另一个具有指向 A 的外键的实体 B。您想将 A 和 B 移动到另一台服务器。现在猜猜会发生什么:A 获得了一个新 ID,您需要手动将链接从 B 转换为 A 才能获得正确的链接。如果你忘记这样做,你要么丢失外键,要么更糟,B 可能突然链接到一个完全不同的实体......使用 UUID,你可以按原样传输数据,而不必担心重新映射外键.

然而,过去每次我提出这个问题时,都会给出相同的评论:“但是你可以有重复项!”。好吧,对于那些喜欢数学的人:如果你在接下来的 100 年里每秒生成十亿个随机 UUID,那么你有 50% 的机会发生一次碰撞(一次!)。从更长远的角度来看,如果您将自己限制在 32 位整数的范围内,则发生碰撞的机会是 1.6 * 10 -27 。如果你不喜欢这些几率,我建议你不要离开家(陨石撞击)、上车(随机车祸)或吃东西(食物中毒)。

所以停止使用数字 ID 并开始使用 UUID。

一个小补充

您有不同版本的 UUID。大多数时候使用版本 1 或 4。

版本 1 是基于时间的,并且对于同一 MAC 地址在 100 纳秒间隔内是唯一的。如果您每秒生成的 UUID 少于 1000 万个,那么可以安全使用(如果这样做,您还有其他问题;))。它的内部计时器在大约 1000 年内环绕,所以我相当确定你在那里很安全,你不必担心赔率。版本 4 是一个基于随机的 UUID,具有我之前提到的重复几率。两者之间的一个重要区别是版本 1 UUID 可以按时间顺序排序,而版本 4 不能。

对于那些强调使用 UUID 导致存储增加的人,请看一下 这个