【问题标题】:How do content addressable storage systems deal with possible hash collisions?内容可寻址存储系统如何处理可能的哈希冲突?
【发布时间】:2026-02-16 05:15:01
【问题描述】:

内容可寻址存储系统使用存储数据的哈希值作为标识符和地址。碰撞非常罕见,但如果系统长时间大量使用,它可能会发生。如果有两条数据产生相同的哈希值会怎样?最近存储的数据不可避免地会获胜并且数据会丢失,或者是否有可能设计一种方法来存储两者并允许访问两者?

为了缩小问题范围,我想重点关注 Camlistore。如果永久节点碰撞会发生什么?

【问题讨论】:

    标签: storage hash-collision future-proof camlistore


    【解决方案1】:

    假设没有发生碰撞。考虑到强大的哈希函数和随意的、非恶意的用户输入,这是一个完全合理的假设。 Camlistore 目前使用的 SHA-1 也可以防止恶意尝试产生冲突。

    如果哈希函数随时间变弱并需要停用,Camlistore 支持为新的 blobref 迁移到新的哈希函数,同时保持旧的 blob ref 可访问。

    如果确实发生了冲突,据我所知,第一个存储的带有该哈希的 blobref 将获胜。

    来源:https://groups.google.com/forum/#!topic/camlistore/wUOnH61rkCE

    【讨论】:

    • 尽管如此,编写一个设计上不可靠的存储软件仍然感觉有些奇怪(冲突确实发生)。人们通常假设只有硬件是在不可靠性的情况下编写的(这个驱动器很可能会在大约 10 年内损坏),而软件被设计为“完美”。
    【解决方案2】:

    在理想的防碰撞系统中,当摄取新文件/对象时:

    1. 计算传入项目的哈希值。
    2. 如果传入的哈希已经存在于存储中:
      1. 项目数据被保存并与哈希关联作为其标识符
    3. 如果传入哈希匹配存储中的现有哈希:
      1. 检索现有数据
      2. 对现有数据与新数据进行逐位比较
      3. 如果发现两个副本相同,则将新条目链接到现有哈希
      4. 如果新副本不同相同,则新数据要么
        1. 被拒绝,或
        2. 附加或前缀* 附加数据(例如时间戳或用户 ID) 并重新散列;然后重复整个过程。

    所以不,信息在内容可寻址存储系统中丢失并非不可避免

    * 理想情况下,现有存储的数据将以相同的方式重新散列,并以某种方式标记原始散列条目(例如链接到零字节有效负载)以表示存在最初解析为该哈希的多个存储对象(在概念上类似于'Disambiguation page' on Wikipedia。是否有必要取决于需要如何从系统中检索数据。


    虽然故意导致冲突对于给定算法可能在天文上是不切实际的,但随机冲突可能会在第二个存储事务时立即发生。


    注意:一些小型/非关键系统会跳过二进制比较步骤,以换取带宽或处理时间的风险。 (通常,只有在某些元数据匹配时才会这样做,例如文件名或数据长度。)

    这种系统的风险概况(例如单个git 存储库)与摄取大量二进制数据的企业/云规模环境有很大不同,尤其是如果该数据是明显的随机二进制数据(例如加密/压缩文件)与滑动窗口重复数据删除之类的结合。


    另见,例如:

    【讨论】:

      【解决方案3】:

      复合键,例如 hash + userId

      【讨论】:

      • 这只会降低碰撞概率,并且可能会产生影响(给定的用户不能与其他人的文件发生碰撞),它仍然不会使碰撞成为不可能。
      • 如果 userId 是一个 UUID 的话,特别是天文数字。