一个月内php独特的id

时间:2013-04-09 13:42:49

标签: php

我需要在一个月内和一年内获得唯一身份证(尽可能多的唯一身份)。代码必须简短。会计软件必须使用代码作为输入/记录的识别号。

如果公司在一个月内的交易不超过10 000个,那么目标就是让它变得独一无二。同样的目标是代码必须尽可能短,并且PHP代码尽可能短,并尽可能少地使用服务器资源。

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

目前决定使用这样的

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

有更好的解决方案吗?

7 个答案:

答案 0 :(得分:11)

我会认为你在愚弄自己。标准的mysql自动增量(INT)将达到4,294,967,296。因此,以每月10万笔交易的速度,这只会持续35,791年。

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

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

答案 1 :(得分:3)

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

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

$userFriendlyId = dechex($id);

并使用hexdec

从用户友好ID进行查询
die(dechex(6000000)); //will output 5b8d80

或其他converting,感谢John。

答案 2 :(得分:3)

首先,我也会去自动增量。即使您选择使用上述代码(月份+随机内容),我也建议您使用数字(int / bigint)自动增量ID。你应该在表面下面使用这个id'使您的代码与数据库通信(引用/查找记录)。

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

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

我建议你自己从字符0-9,a-z和A-Z生成一个随机字符串,它为每个字符提供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);

我也会在月份和随机字符之间省略短划线(&#39; -&#39;)因为这可以节省1个字符,而且你知道前两个字符将始终是数字这个月。

编辑:完成一些测试

我已经为碰撞做了一些测试: 我已经将100个随机字符串渲染了100次,并且每次都检查它的唯一性。用长度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

绝对0%的碰撞几率不能被Mark B指出生日问题指出。

答案 3 :(得分:1)

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

答案 4 :(得分:0)

date("m").'-'.time().rand(0,9999) 
我认为

就足够了。

答案 5 :(得分:0)

我建议使用几位哈希

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

但我没有。 出于会计原因,输出中唯一主键与日期('m-Y')的组合可能会好得多。

答案 6 :(得分:-1)

如果使用公司ID,我相信你们已经拥有月份/年份和md5,然后使用前10个字符。这将永远是独一无二的。