bal*_*pha 7 language-agnostic unique
有许多系统依赖于某些特定值的唯一性.任何使用GUID的东西都会浮现在脑海中(例如,Windows注册表或其他数据库),但也会从对象创建哈希以识别它,因此需要此哈希是唯一的.
哈希表通常不介意两个对象是否具有相同的哈希,因为哈希仅用于将对象分解为类别,因此在查找时,不是表中的所有对象,而只是同一类别中的那些对象(必须将搜索对象的身份进行比较.
然而,其他实现(似乎)取决于唯一性.我的例子(这就是让我问这个的原因)是Mercurial的修订版ID.一进入 Mercurial的邮件列表中正确地指出:
在您的第一个十亿次提交中,变更集哈希意外冲突的几率基本为零.但我们会注意到它是否会发生.你会因为偶然打破SHA1而成名.
但即使是最小的概率并不意味着不可能.现在,我不想解释为什么完全可以依赖于唯一性(这已经在这里讨论了).这对我来说非常清楚.
相反,我想知道(也许通过你自己的工作中的例子):
是否有任何最佳做法来涵盖这些不可能的案例?
它们是否应该被忽略,因为特别强烈的太阳风更有可能导致硬盘读取错误?
他们至少应该进行测试,如果只是因为"我放弃了,你已经完成了不可能的"消息而失败了吗?
或者甚至应该优雅地处理这些案件?
对我来说,特别是下面的内容很有趣,尽管它们有点敏感:
如果你不处理这些案件,你会如何对付不听概率的直觉?
如果你确实处理过它们,你如何证明这项工作是合理的(对你自己和他人而言),考虑到你有更多可能的案例你不能处理,比如超级新星?
答案就是你没有测试发现偶然发生的GUID冲突.您正在测试发现由于GUID代码中的错误而发生GUID冲突,或者GUID代码依赖于您违反(或被某些攻击者违反)的前提条件,例如在V1中MAC地址是独一无二的,时间在前进.要么比基于超新星的bug更有可能.
但是,并非GUID代码的每个客户端都应该测试其正确性,尤其是在生产代码中.这就是单元测试应该做的事情,所以要省去错过你的实际使用会遇到的但是单元测试没有的错误的成本,而不是一直猜测你的库的成本.
另请注意,GUID仅在生成它们的每个人合作时才有效.如果您的应用程序在您控制的计算机上生成ID,那么您可能不需要GUID - 像递增计数器这样的本地唯一ID可能对您没问题.显然Mercurial不能使用它,因此它使用哈希值,但最终SHA-1将陷入产生冲突的攻击(或者更糟糕的是,预映像),并且它们必须改变.
如果您的应用程序在您无法控制的计算机上生成非哈希"GUID"(如客户端),那么就会忘记意外冲突,您会担心恶意客户试图管理您的服务器时会发生故意的冲突.无论如何,保护自己不会对事故造成伤害.
答案可能是"不".如果你可以优雅地处理冲突的GUID,就像哈希表一样,那么为什么还要使用GUID呢?"标识符"的重点在于,如果两个东西具有相同的ID,那么它们就是相同的.如果你不想对它们进行同样的处理,最初只是像哈希表一样将它们引导到桶中,然后使用不同的方案(如哈希).