9

我想要做的是为我网站上的文章创建一个 12 个字符的 ID,类似于 youtube 如何处理他们的视频 ID ( http://www.youtube.com/watch?v=53iddd5IcSU )。现在我正在生成一个 MD5 哈希,然后像这样抓取它的 12 个字符:

$ArticleId = substr(MD5("Article".$currentID),10,12)

其中 $currentID 是数据库中的数字 ID(例如 144)

我有点偏执,我会遇到重复的 $ArticleId,但实际上发生这种情况的可能性有多大?而且,由于我的数据库中的列是唯一的,我怎样才能处理这种罕见的情况而不会抛出一个丑陋的错误?

PS 我制作了一个小脚本来检查前 5000 个 $ArticleId 中的重复项,但没有。

编辑:我不喜欢 base64_encode 哈希的样子,所以我这样做了:

function retryAID($currentID)
{
    $AID = substr(MD5("Article".$currentID*2),10,12);

    $setAID = "UPDATE `table` SET  `artID` =  '$AID' WHERE `id` = $currentID ";
    mysql_query($setLID) or retryAID($currentID);
}


$AID = substr(MD5("Article".$currentID),10,12);

$setAID = "UPDATE `table` SET  `artID` =  '$AID' WHERE `id` = $currentID ";
mysql_query($setAID) or retryAID($currentID);

由于 AID 列是唯一的,因此 mysql_query 将抛出错误,并且 retryAID 函数将找到唯一的 id ...

4

4 回答 4

6

使用顺序 ID 有什么问题?数据库将为您处理此问题。

除此之外,12 个字符仍然是 96 位。2 96 = 79228162514264337593543950336 个可能的哈希值。尽管已知 MD5 存在碰撞漏洞,但发生碰撞的可能性与实际看到碰撞的可能性之间存在天壤之别。

更新:

根据您使用的 PHP md5函数的返回值,我上面的数字不太正确。

将哈希作为 32 个字符的十六进制数返回。

由于您从 32 个字符的十六进制数中获取 12 个字符(而不是 128 位哈希的 12 个字节),因此最终可能得到的实际哈希数为 16 12 = 281474976710656。仍然不少。

于 2010-02-14T04:11:23.130 回答
1
<?php
  function get_id()
  {
    $max = 1679615; // pow(36, 4) - 1;
    $id = '';

    for ($i = 0; $i < 3; ++$i)
    {
      $r = mt_rand(0, $max);
      $id .= str_pad(base_convert($r, 10, 36), 4, "0", STR_PAD_LEFT);
    }
    return $id;
  }
?>

返回一个以 36 为基数的 12 个字符的数字,它给出了 4,738,381,338,321,616,896 种可能性。(碰撞概率取决于随机数生成器的分布。)

为确保没有冲突,您需要循环:

<?php
do {
  $id = get_id();
} while ( !update_id($id) );
?>
于 2010-02-14T05:41:39.087 回答
0

UUID 怎么样?

http://php.net/manual/en/function.uniqid.php

于 2010-02-14T05:16:41.180 回答
0

不,不是很独特。

如果您需要更短的时间,为什么不对其进行 base64 编码?

于 2010-02-14T04:09:23.743 回答