1

在一个月和一年中,我需要唯一的 ID(尽可能唯一)。代码必须简短。会计软件需要代码作为条目/记录的识别号。

如果公司在一个月内的交易不超过 10 000 次,则目标是使其独一无二。另一个目标是代码必须尽可能短,并且 php 代码尽可能短并且使用尽可能少的服务器资源。

不能使用 Mysql 自动增量,例如如果每个月有 10 000 个事务,那么几年后这个数字会很长。

目前决定使用这样的

 date("m"). '-' .substr(md5(uniqid(rand(), true)), -20, 4);

有更好的解决方案吗?

4

7 回答 7

11

我会承认你在自欺欺人。一个标准的 mysql 自动增量 (INT) 将上升到 4,294,967,296。因此,以每月 10,000 笔交易的速度计算,您只能使用 35,791 年。

当然,如果这还不够,您可以使用 BIGINT,在这种情况下,您将有 153,722,867,280,912 年的时间来解决问题。这比预测的宇宙寿命长了好几倍。

这种事情是自动增量的确切用例。

于 2013-04-09T13:52:25.993 回答
3

50年后,您的 ID 将为50x12x10.000 = 6.000.000。这是非常小的 ID mysql

如果您不想向您的用户显示那个长 ID,您可以执行dechex

$userFriendlyId = dechex($id);

并使用hexdec从用户友好的 id 进行查询

die(dechex(6000000)); //will output 5b8d80

或其他转换,感谢约翰。

于 2013-04-09T13:53:35.713 回答
3

首先,我也会选择自动增量。即使您选择使用提到的代码(月份+随机内容),我也建议您使用数字(int/bigint)自动增量 id。您应该使用此 id '在表面之下'让您的代码与数据库进行通信(引用/查找记录)。

因此,对于“月份+随机内容”标识符,我不建议使用任何东西,uniqid()因为它基于微秒,如果两个事务将在同一微秒发生,则不是唯一的。另外我不鼓励使用md5(),因为这个函数对于散列非常有用,但是如果你只使用它来生成字符,它会大大降低你的代码速度。

此外,您自己的代码建议会生成 4 个随机字符,可能是 0-9 或 af(十六进制),为您提供 16 种可能性。16 种可能性的 4 个字符为您提供 16x16x16x16 = 65,536 个唯一字符串。很有可能在渲染 10,000 个这些字符串时,您会得到重复项。

我建议您自己从字符 0-9、az 和 AZ 生成一个随机字符串,每个字符为您提供 36 种可能性,4 个字符为您提供 36x36x36x36 = 1,679,616 个唯一字符串。更多的字符可以减少重复(碰撞)的可能性。你可以这样做:

function randString($length = 4) {
    $randChars = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randString = ''; 
    while (strlen($randString) < abs(intval($length))) {
        $randString .= substr($randChars, rand(0, strlen($randChars)-1), 1); 
    }   
    return $randString;
}

$id = date('m') . randString(4);

我还会-在月份和随机字符之间省略破折号(''),因为这样可以为您节省 1 个字符,并且您知道前两个字符将始终是月份的编号。

编辑:做了一些测试

我已经对碰撞进行了一些测试:我已经渲染了 10,000 个随机字符串一百次,并且每次都检查唯一性。使用长度 3、4(如您所做的)、5 和 6 完成此操作。结果如下:

-------- Length 3 ------------
Minimal duplicates: 170
Maximum duplicates: 241
Average duplicates: 207.05
-------- Length 4 ------------
Minimal duplicates: 0
Maximum duplicates: 8
Average duplicates: 3.19
-------- Length 5 ------------
Minimal duplicates: 0
Maximum duplicates: 2
Average duplicates: 0.05
-------- Length 6 ------------
Minimal duplicates: 0
Maximum duplicates: 0
Average duplicates: 0

正如Mark B在提到生日问题时也指出的那样,不能排除绝对 0% 的碰撞几率。

于 2013-04-09T14:12:58.020 回答
1

只需使用uniqid()。它旨在产生全球独特的价值,而不仅仅是每个月或每年的独特价值。

于 2013-04-09T13:52:39.723 回答
0
date("m").'-'.time().rand(0,9999) 

我想就够了。

于 2013-04-09T13:49:17.130 回答
0

我会建议几个数字哈希

 $random_hash = substr(md5(uniqid(rand(), true)), 10, 10);
 echo date('m-Y-').$random_hash ;

但我没有。出于会计原因,输出中唯一主键与 date('mY') 的组合可能会更好。

于 2013-04-09T13:58:55.263 回答
-1

怎么样使用公司ID,我相信你们有,月/年和md5,然后取前10个字符。这将永远是独一无二的。

于 2013-04-09T13:51:22.843 回答