防伪唯一序列号生成

时间:2018-01-15 08:57:50

标签: php mysql batch-file random unique

我正在尝试生成一个随机序列号以放置全息贴纸,以便让客户检查所购买的产品是否真实。

序: 一旦您输入并查询该代码,它将被取消,因此下次再次执行此操作时,您会收到一条消息,指出该产品可能是假的,因为代码已被使用。

考虑到我应该为每年生产不超过2/3百万件的工厂制造这个系统,对我来说有点难以理解如何设置所有东西,至少第一次......

我想到了4组中的20位数代码(没有字母,因为用户必须非常容易阅读并输入代码)

12345-67890-98765-43210

我认为这是最简单的方法:

function mycheckdigit()
{
...
return $myserial;
}
$mycustomcode="123";
$qty=20000;
$myfile = fopen("./thefile.txt","w")  or die("Houston we got a problem here");
//using a txt file for a test, should be a DB instead...
for($i=0;$i<=$qty;$i++) {
    $txt = date("y").$mycustomcode.str_pad(gettimeofday()['usec'],6,STR_PAD_LEFT).random_int(1000000,9999999). "\n";
    //here the code to make check digits
    mycheckdigit($txt);
    fwrite($myfile,$myserial);
}
fclose($myfile);
  • 第一组识别年份:18和3自定义代码
  • 第二组包括microtimegettimeofday()['usec']
  • 第3次完全随机
  • 最后一组包括3个随机数和1组校验位以及2组校验位

简而言之:

Y= year
E= part of the EAN or custom code
M= Microtime generated number (gettimeofday()['usec'])
D= random_int() digits
C= Check Digit

YYEEE-MMMMM-MDDDD-DDDCC

通过这种方式,我有一个每年都有变化的前缀,我可以识别出该产品是什么品牌(所以我只能使用一个数据库源)而且我仍然有足够的随机数字 - 也许 - 非常独特如果我考虑我只会“提取”1,000,0009,999,999中的部分数字,然后使用上面的排序将其拆分

有些问题:

  • 你认为我有足够的组合,一年内不会生成相同的代码,考虑到200万个代码吗?如果没有必要,我不会在数据库中使用查找相同的代码,因为这会减慢批量生成(在生产过程中批量执行)
  • 可以更好地添加一些唯一标识符,例如一年中的某一天(001-365)并使random_int()缩短3位数?请考虑我将每月生成代码而不是每天生成代码(但我认为唯一性没有大的变化)
  
      
  • 考虑到PHP中的后端我想使用mt_rand()函数,可能是一个很好的方法吗?
  •   

更新:在@apokryfos建议之后,我阅读了有关UUID生成和类似内容的更多内容我发现使用random_int()代替了一个很好的折衷方案。 因为我只需要数字,所以HEX哈希对我的需求没用,并且使事情变得更复杂

我会避免使用像RSA密钥等复杂的加密内容...... 我不需要那种级别的安全性和复杂性,我只需要一种方法来生成一个唯一的序列号,尽可能最独特,如果你不刮开贴纸就不容易被猜到和取消(所以数字创建应该不是A到Z,而是随机的)

1 个答案:

答案 0 :(得分:0)

你可以每年玩11个随机数字,这样11位数字1到99999999999(999亿就超过200万)所以w.r.t.足够的组合,我认为你被覆盖。

然而,使用mt_rand您很可能会发生冲突。在使用数据库之前,这是一种计划200万随机数的方法:

<?php
$arr = [];
while (count($arr) < 1000000) {
    $num = mt_rand(1, 99999999999);
    $numStr = str_pad($num,11,0,STR_PAD_LEFT); //Force 11 digits
    if (!isset($arr[$numStr])) {
        $arr[$numStr] = true;
    } 
}
$keys= array_keys($arr);

碰撞次数通常较低(第一次碰撞发生在大约300 000 - 500 000个数字,因此非常罕见。

数组$keys中的每个值都是一个11位数字,它是随机且唯一的。

这种方法相对较快但要注意它需要相当多的内存(超过128MB)。

这就是说,一种更常用的方法是生成universally unique identifier (UUID),它更有可能是唯一的,因此不需要检查唯一性。