浅谈几种常见的分布式ID
UUID是可以生成时间、空间上都独一无二的值,其本质是随机 规则组合而成的。即使在两个独立的服务器上生成UUID,其预期值也是不同的。以MySQL为例,说明下UUID。
格式
在MySQL中,UUID值是一个128位的数字,表示为以下格式的十六进制数字的utf8字符串:aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee。其得到的随机值由5个部分组成,且分隔符位为:中划线。其各部分含义如下:
前三组值是时间戳换算过来的;第四组值是暂时性保持时间戳的唯一性。例如,使用夏令时;第五组值是一个IEE 802的节点标识值,它是空间上唯一的。若后者不可用,则用一个随机数字替换。假如主机没有网卡,或者我们不知道如何在某系统下获得机器地址,则空间唯一性就不能得到保证,即使这样出现重复值的几率还是非常小的。
在MySQL环境中多次调用或执行得到的后两组值相同,若把mysqld服务器关闭,重新启动之后,会发现第四组的组与未重启前的值发生变化,然后一直不变化,只要重新启动mysqld服务就会发生变化。另外,对于同一台机器,第五组值始终不会发生变化。
优点
使用UUID作为主键具有以下优点:
UUID值在表,数据库甚至在服务器上都是唯一的,允许您从不同数据库合并行或跨服务器分发数据库。UUID值不会公开有关数据的信息,因此在URL中使用更安全。可以在避免往返数据库服务器的任何地方生成UUID值。它也简化了应用程序中的逻辑。
缺点
除了优势之外,UUID值也存在一些缺点:
存储UUID值(16字节)比整数(4字节)或甚至大整数(8字节)占用更多的存储空间。调试似乎更加困难,想象一下WHERE id =9d6212cf-72fc-11e7-bdf0-f0def1e6646c和WHERE id = 10哪个舒服一点?使用UUID值可能会导致性能问题,因为它们的大小和没有被排序。
数据库案例:MySQL
在MySQL中,就内置了对UUID的支持。在使用上需注意若干问题。
作为主键问题
UUID()函数产生的值,并不适合作为InnoDB引擎表的主键。因为格式无序,作为索引组织表存储会带来管理上的不小开销。
格式问题
在MySQL中,可以使用UUID()来生成主键,但是用MySQL的UUID()函数 ,生成的UUID是36位的,其中包含32个字符以及4个分隔符(-),往往这个分隔符对我们来说是没有用的,可以使用MySQL自带的REPLACE函数去掉分隔符。
内置函数
支持在MySQL中,可以以紧凑格式(BINARY)存储UUID值,并通过以下功能显示人机可读格式(VARCHAR):UUID_TO_BIN、BIN_TO_UUID、IS_UUID。需要注意,UUID_TO_BIN(),BIN_TO_UUID()和IS_UUID()函数仅在MySQL 8.0或更高版本中可用。- UUID_TO_BIN()函数将UUID从人类可读格式(VARCHAR)转换成用于存储的紧凑格式(BINARY)格式- BIN_TO_UUID()函数将UUID从紧凑格式(BINARY)转换为人类可读格式(VARCHAR)- IS_UUID()函数则可用来判断参数是有效的字符串格式UUID。
2. NanoID
UUID 是软件开发中最常用的通用标识符之一。然而,在过去的几年里,其他的竞品挑战了它的存在。其中,NanoID 是 UUID 的主要竞争对手之一。但是,这两者之间的主要区别很简单。它归结为键所使用的字母表。由于 NanoID 使用比 UUID 更大的字母表,因此较短的 ID 可以用于与较长的 UUID 相同的目的。
优点
更小
NanoID 只有 108 个字节那么大。与 UUID 不同,NanoID 的大小要小 4.5 倍,并且没有任何依赖关系。此外,大小限制已用于将大小从另外 35% 减小。大小减少直接影响数据的大小。例如,使用 NanoID 的对象小而紧凑,能够用于数据传输和存储。随着应用程序的增长,这些数字变得明显起来。
更安全
在大多数随机生成器中,它们使用不安全的 Math.random()。但是,NanoID 使用 crypto module 和 Web Crypto API,意味着 NanoID 更安全。此外,NanoID 在 ID 生成器的实现过程中使用了自己的算法,称为 统一算法,而不是使用“随机 % 字母表” random % alphabet。
更快
NanoID既快速又紧凑,NanoID 比 UUID 快 60%。与 UUID 字母表中的 36 个字符不同,NanoID 只有 21 个字符。
更多语言
NanoID 支持 14 种不同的编程语言,它们分别是:C#、C 、Clojure 和 ClojureScript、Crystal、Dart