我们的世界被编号了。书籍有ISBN,产品有条形码。汽车有 车辆识别码(VIN),甚至人都有社会安全号码。
数字帮助我们明确地引用物品。“John Smith”可能对应很多人,但社会安全号码123-45-6789精确地指向一个人。
GUID(全局唯一标识符)是一种更大、更强的ID号码。你可能会看到UUID(通用唯一标识符)这个术语被随意使用,这个词有些吹毛求疵,用于那些不仅在全局,而且在整个宇宙中都唯一的数字。
无论你怎么称呼,GUID或UUID都只是巨大的ID号码。
计数的问题
“我们才不需要什么讨厌的GUID,”你可能会在一大口Top Ramen的间隙想,“我就用普通数字,从1开始计数。”
当然,这听起来很简单。从ISBN #1开始,每本新书加一。但问题出现了:
- 谁来计数?一个中央权威?
- 谁处理并发请求并消除重复?
- ID可以在不同产品间共享吗?社保号1是否与ISBN 1不同?
- 人们能猜到下一个ID是什么吗?已经发放了多少个ID?
计数的问题在于我们希望 创建ID号,无需管理麻烦.
GUID来救援
GUID是大的、巨大的数字,几乎保证唯一。它们通常是128位长,看起来像这样 以十六进制表示:
30dd879c-ee2f-11db-8314-0800200c9a66
格式是一个定义良好的32个十六进制数字序列,分组为8-4-4-4-12。这给了我们 2^128 或大约 10^38个数字.
以下是GUID背后的思路:
如果你选择一个巨大的随机数(39位长),那 极不可能 别人选到相同数字的概率极低。
GUID不与特定产品绑定。GUID可以用于人、汽车、文件、网页、颜色等任何事物。对于常规的注册号码,你从1开始计数,数字可能重叠。社会安全号码123-45-6789不同于ISBN 123456789,也不同于条形码123456789。这在使用GUID时不是问题。
这取决于阅读GUID的人如何理解GUID的上下文。GUID数量极其庞大,你可以用它们来编号所有东西而不会耗尽。
GUID(全局唯一标识符)为您提供一个可用于宇宙中任何物品的唯一序列号。
巨大的GUID短缺
学习GUID时,感觉区区39位数字似乎不够。如果人们滥用GUID,给宠物到最爱的口香糖口味都分配一个,难道不会耗尽吗?
让我们看看。想想互联网有多大:Google的索引中有数十亿个网页。就算它有一万亿(10^12)好了。再想想维基百科的每篇文章、CNN的每条新闻、亚马逊的每个产品、任何作者的每篇博客。我们可以为这些文档中的每一个分配一个GUID。
现在假设地球上的每个人都拥有他们自己的一份互联网来跟踪自己的东西。甚至更疯狂,假设每个人每秒都得到一份自己的互联网副本。我们能坚持多久?
让我再说一遍。每个人得到一份 每秒钟获取整个互联网的个人副本,持续十亿年.
这是一个令人难以置信的项目数量,很难理解。相信我,我们不会很快用完GUID。如果真用完了呢?我们会开始使用更多位数的GUID。
使用GUID
如果你想创建GUID,试试
- 在线GUID生成器
- GUID库适用于 PHP, Perl, Ruby, Python, .NET
- usesguid plugin 用于Ruby on Rails:在数据库中使用GUID代替整数作为主键。
有几种创建GUID的方法(RFC 4122 描述了约定),但你应该避免混乱并使用库。GUID的一般类型是:
- 随机: 只需使用系统的随机数生成器创建一个128位的数字。
- 基于时间: 基于当前时间创建一个GUID。
- 基于硬件: 创建一个GUID,其中某些部分基于硬件特性,例如网卡的MAC地址。这并不好,因为GUID不是“匿名的”,并且可以部分追溯到生成它的机器。
- 基于内容(数据的MD5或SHA-1哈希值): 基于文件内容的哈希创建一个GUID。内容相同的文件将获得相同的GUID。你还可以使用唯一的命名空间(如你的URL)作为哈希的种子。
你可以混合使用上述技术。如果你希望重复文件具有相同的GUID,则使用基于内容的GUID。如果你希望GUID唯一,即使内容相同,则随机创建或结合文件内容和随机数创建。
GUID示例
以下是一些你可以用GUID做的事情:
- 数据库中的唯一主键。这使得在不同机器上创建的数据库项可以稍后合并而不发生冲突,且无需中央服务器来管理ID。
- 上传文件的唯一文件名。如果文件的每个版本都有其自己的GUID,你可以设置 长缓存过期时间.
- 资源的唯一名称(例如instacalc的del.icio.us URL): http://del.icio.us/url/6c5ff0ed608e75724df94a52b05dd6a8)
- 允许供应商在不联系中央权威机构的情况下创建和注册唯一ID(例如 COM中的类ID)
GUID的权衡
像生活中的大多数事情一样,GUID有优点和缺点。权衡特性以确定它们是否有意义:
优点:
- 无中央权威: 你避免了管理的需要,但无法跟踪已分配的内容。一种折衷方案是内部生成GUID,然后分发。
- 易于合并: 你可以合并来自不同数据源的GUID集合,冲突概率微乎其微。
缺点:
- 表面随机: 用户很难猜出未知对象的ID。这对安全有好处,但对调试不利。
- GUID开销: GUID是时空权衡的一个例子。你在合并时节省了时间,但需要使用空间来存储较大的(16字节)GUID。用一个16字节的GUID来跟踪数据库中一个4字节的项可能没有意义。
GUID并非保证
对于GUID有一个巨大的警告:仍然可能发生冲突。
首先, 生日悖论 向我们展示了冲突的概率为 使用GUID。GUID发生冲突的可能性非常非常小,但随着分配数量的增加,可供选择的剩余数量会减少。
第二,恶意用户可能试图劫持他知道将要被使用的GUID(假设用户可以分配自己的GUID),或者将不同的内容重新提交到先前的GUID(将文件A提交到文件B的哈希下)。
如果你在编写软件,要进行防御性编程,检测GUID已经存在的情况。向用户显示错误,或者更好的是,恢复,在服务器端创建一个新的GUID并重试。GUID很好,但它们不是魔法子弹。
一如既往,我们学无止境。在这里了解更多关于GUID的信息:
- 通用唯一标识符(UUID) URN命名空间
- Coding Horror: 主键与GUID
- 维基百科关于 全局唯一标识符(GUID) 和 通用唯一标识符(UUID)