一、UUID
如果说到UUID,有过互联网开发经验的一般都会嘿嘿一笑,个中的滋味,都有自己的理解。UUID,通用唯一标识符。是一种128位的标识符,目的是在分布式系统中无需中心协调即可生成唯一ID。它的优势就在于全局的单纯的唯一性,而不用考虑是否有无中心。这就让它在分布式系统中的一些唯一标识应用中能够大显身手。
需要说明的是,UUID是有多个版本的,为了跟上技术发展的脚步,UUID也推出了从V1~V7几个版本。V1版本是基于时间戳和MAC地址的,虽然能够保证唯一性但存在着隐私泄露的风险;而V4版本虽然完全随机生成,安全性高但其高度随机性导致在数据库等应用中受限;而最新的V6和V7则按时间戳排序,在数据库中的应用更友好。
现在常用的经常是以UUIDv4最多也最广泛。所以下面如果不特指一般针对的是UUIDv4版本。
二、特点和应用
在上面的分析可以得知,UUID特别适合于分布式中无中心化的唯一ID的使用。它的主要特点在于:
- 可以完全去中心化
非约束性的产生ID而不需要中心化的干预 - 全局唯一性
即不用考虑是否因为分布式导致重复分配而产生的问题 - 安全性和隐私性
早期版本虽然有安全性等小问题但在高版本已经解决 - 广泛支持性
由于出现时间早,所以现在基本各类语言都支持UUID
正是因为这些特点,UUID的应用场景也非常广泛,理论上凡是需要确保唯一ID应用的场景都可以使用。但实际上由于某些具体的情况,如V4版本的完全随机性,导致对数据索引支持不友好,引起大量的页分裂。在写入场景下根本不能为开发者接受。
三、问题
老生常谈的是,一门技术,有它的长处就必然会有其短处。长处越明显,短处则越明显。正所谓“优势就是最大的劣势”。对于UUIDv4来说,其存在的主要问题包括:
- 索引支持差
这个刚刚提到了,由于插入值的完全随机,无法形成局部优势,导致对数据库底层B-TREE的不友好。每次写都要加载不同 页。而在MySQL的InnoDB中,由于聚簇(主键)索引的物理存储顺序与主键索引排序的,所以使用UUID会导致写入慢几倍而索引体积增大30%以上。同时,随机导致缓存命中率低,性能也会下降 - 无法排序
完全随机性也意味着不可排序,而排序在很多场景下是非常重要的。而因此再增加一个排序字段(如时间)既浪费空间又浪费时间 - 浪费空间
UUID长度有128位,而真正有用的信息并不多,对于海量数据操作的互联网企业来说,有点浪费 - 信息泄露风险
UUIDv1以MAC地址信息为基础,有可能会导致信息的泄露
一门技术应用越广泛,那么它暴露出来的问题越多。这是好事,一个是推进技术的迭代完善,另外一个可以刺激更新的技术产生。
四、应对和解决
面对UUID上述的问题,开发者们也可以采用下面的方案进行处理:
- 从数据库应用角度看,可以采用优化存储结构,使用替代的自增ID或更新版本的UUIDv7
- 考虑使用其它ID方案,如ULID或Snowflake ID(Twitter的64位ID)
总归就是一句话,哪种方式更容易引入并能解决当前的问题,就使用哪个。
五、总结
正如矛与盾的对立统一。它们互相攻击互相克制,然后又互相发展。虽然在某个时期可能有一方逞一时之强。但从整体来看,矛与盾是平衡的,在互相对抗中共同进步。UUID也是如此,有缺点就会有进步,有进步就会有新的缺点。如此反复,直到被更新的技术替代。