优秀的生成防伪码的代码应该如何写?百万千万量级别的。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
DavidNineRoc
V2EX    问与答

优秀的生成防伪码的代码应该如何写?百万千万量级别的。

  •  
  •   DavidNineRoc 2018-03-23 10:01:53 +08:00 3615 次点击
    这是一个创建于 2810 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求:

    • 生成的防伪码长度大概在 12~18 位
    • 有可能是纯数字,或者字母+数字
    • 绝对不能重复 某 cms 防伪系统的生成防伪码的源码;
    function genRandomString($len, $t = 0) { $chars = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "2", "3", "4", "5", "6", "7", "8", "9"); $chars1 = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"); $chars2 = array("1", "2", "0", "3", "4", "5", "6", "7", "8", "9"); $chars3 = array("A", "B", "C", "D", "E", "F", "G", "O", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"); if ($t == 1) { $charsLen = count($chars1) - 1; shuffle($chars1); $output = ""; for ($i = 0; $i < $len; $i++) { $output .= $chars1[mt_rand(0, $charsLen)]; } } else if ($t == 2) { $charsLen = count($chars2) - 1; shuffle($chars2); $output = ""; for ($i = 0; $i < $len; $i++) { $output .= $chars2[mt_rand(0, $charsLen)]; } } else if ($t == 3) { $charsLen = count($chars3) - 1; shuffle($chars3); $output = ""; for ($i = 0; $i < $len; $i++) { $output .= $chars3[mt_rand(0, $charsLen)]; } } else { $charsLen = count($chars) - 1; shuffle($chars); $output = ""; for ($i = 0; $i < $len; $i++) { $output .= $chars[mt_rand(0, $charsLen)]; } } return $output; } 

    1 基本就是金刚葫芦娃,一股脑生成,插入数据库。连判断都没有。虽然重复的概率小,但还是有可能呀。怎么做到一个优秀一点的?

    • 我想的就只是插入的时候返回 0 或者 1,循环结束计算返回 1 的集合,是否等于要生成的防伪码数量,如果不等于,(这时候,数量级已经下降了很多)
    • 来一个死循环,一次生成一个插入数据库,知道成功的条数弥补上一次重复的数量,跳出循环。

    有没有更好的方法?

    第 1 条附言    2018-03-23 16:13:06 +08:00

    是防伪码呀 >_<

    17 条回复    2018-03-24 23:01:59 +08:00
    ryd994
        1
    ryd994  
       2018-03-23 10:11:51 +08:00 via Android
    验证码这种使用场景,难道不该上 redis 么?重启就重启,反正丢几个验证码有没什么大事,用户只会怀疑自己打错了
    arron
        2
    arron  
       2018-03-23 10:28:28 +08:00
    如果是批量,你就加两个干扰项:time, index 至于放进去怎么变化看需求,可以保证你生成的字符串不会重复。如果是用的时候再生成,那么 time + rand 基本就可以了,保证重复概率低。
    whileFalse
        3
    whileFalse  
       2018-03-23 11:08:44 +08:00
    uuid 不行吗
    oott123
        4
    oott123  
       2018-03-23 11:41:17 +08:00 via Android
    数据库做个唯一性索引,插崩了就重新插一下
    loveCoding
        5
    loveCoding  
       2018-03-23 11:53:43 +08:00
    生成的防伪码长度大概在 12~18 位
    有可能是纯数字,或者字母+数字

    楼上说的 uuid 满足需求的
    DavidNineRoc
        6
    DavidNineRoc  
    OP
       2018-03-23 13:05:48 +08:00
    @ryd994 不是验证码,是防伪码 >_<
    @arron 真的不是验证码,是防伪码
    @whileFalse 给客户使用的,就是验证是否是正品的防伪码
    @oott123 这个,每次都插入,不如我的第二个方法

    * 我想的就只是插入的时候返回 0 或者 1,循环结束计算返回 1 的集合,是否等于要生成的防伪码数量,如果不等于,(这时候,数量级已经下降了很多)
    * 来一个死循环,一次生成一个插入数据库,知道成功的条数弥补上一次重复的数量,跳出循环。


    @loveCoding uuid 肯定不符合要求,长度太长,而且总是英文数字混合的。想要纯数字根本不可能
    prolic
        7
    prolic  
       2018-03-23 13:12:45 +08:00 via Android
    这需求数字加盐散列不就够了么,信不过 md5 你可以再去一次重
    rrfeng
        8
    rrfeng  
       2018-03-23 13:15:26 +08:00 via Android
    防伪:
    发出去的存起来
    算法自验证

    楼上都在说什么...
    DavidNineRoc
        9
    DavidNineRoc  
    OP
       2018-03-23 16:12:09 +08:00
    @prolic 我真的再说防伪码 >_<
    @rrfeng 生成是问题
    l12ab
        10
    l12ab  
       2018-03-23 16:30:53 +08:00 via iPhone
    类似于卖软件的生成序列号
    LukeChien
        11
    LukeChien  
       2018-03-23 19:56:51 +08:00 via Android
    时间戳+aes(时间戳,秘钥)
    chinvo
        12
    chinvo  
       2018-03-23 19:59:41 +08:00
    Sonyflake-like 的串号,加上校验位
    DavidNineRoc
        13
    DavidNineRoc  
    OP
       2018-03-23 23:13:53 +08:00
    @l12ab 对,差不多就是这样
    @LukeChien 不行,会重复
    @chinvo 能生成纯数字?
    chinvo
        14
    chinvo  
       2018-03-23 23:19:44 +08:00
    @DavidNineRoc #13 你的范例代码不是字母数字混合的么……

    如果要纯数字,那就用时间戳+自增,配合一到两位校验
    DavidNineRoc
        15
    DavidNineRoc  
    OP
       2018-03-24 08:25:35 +08:00
    @chinvo 看 $chars3,时间戳都有十位了,再加自增?一次生成十万百万级别的,基本就出现重复了
    xml123
        16
    xml123  
       2018-03-24 09:25:03 +08:00 via Android
    时间戳是唯一的,就算占了全部的位数,也不会重复啊
    DavidNineRoc
        17
    DavidNineRoc  
    OP
       2018-03-24 23:01:59 +08:00
    @xml123 你还年轻,来点并发,就会重复了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4797 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 09:49 PVG 17:49 LAX 01:49 JFK 04:49
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86