如何为存储在服务器上的文件生成有保证的唯一 ID?

How to generate guaranteed unique id for files stored on server?

我是服务器端编程的新手。目前我正在编写一项服务来存储从 ios 应用程序发送的用户文件。我想为每个文件生成一个唯一的 ID,并将其用作文件名。问题是,我在网上找到的很多解决方案,比如使用哈希函数,都有碰撞的风险。那么这样做的首选方式是什么?我知道 AWS s3 为每个文件生成一个唯一的 ID。他们是如何实施的?

无论您使用什么编程语言,都可能有一个 GUID(有时称为 UUID)库,可以认为它是普遍唯一的。参见 https://en.wikipedia.org/wiki/Universally_unique_identifier

散列根本解决不了这个问题,因为散列的要点是两个相同的输入应该产生两个相同的输出。因此,如果两个用户上传 ThisIsAFile.pdf 都必须说 a89na3 并且会发生冲突。

一种可能的方法是生成一些宽随机 id。如果您生成一些包含几十个字符的随机名称,例如 _5E960vkoXF8_6t2yfMbEM0A_6uBsy060PxH_2YKKKmZkTR6,则碰撞概率可以小到可以忽略不计(例如,您的系统需要 运行 数十亿年才能观察到一次碰撞)。如果您想估计该概率,请使用 birthday problem 方法。

(碰撞并不总是一个问题,如果你能让它们的概率足够小的话)

UUIDs are exploiting this idea. So the simplest way is simply to use a library function generating them, e.g. uuid_generate。您可能想做同样的事情(即编写您自己的随机 ID 生成器),但您需要注意随机性。

至少,你可以用一个 PRNG (such as a Mersenne twister one) that you would seed periodically (and at startup) with some random noise, e.g. using /dev/random (read carefully random(4)...) or getrandom(2). Or you could buy some random generating hardware source (like OneRNG).

顺便说一句,如果你假设用户的文件内容不会改变(所以每个文件在创建时只写一次),你可以使用一些cryptographic hash function on them (like SHA 256). Then if two distinct users would upload exactly the same content (for example, the text of GPLv3)你会把它存储一次 在您的磁盘上(在某些 共享 文件中)。这 https://www.softwareheritage.org/项目正在使用这种技术。

(由于基数原因,理论上仍可能发生冲突,但可能性很小)

您不想让 collisions 在数学上变得不可能。您可能确实想让它们变得非常不可能:如果概率小于 10-50(或者只是 10-30,即大约 2-100) 你可能不在乎(因为我们的地球行星会在碰撞可能发生之前消失)。