【问题标题】:Generate 5 million unique codes生成 500 万个唯一代码
【发布时间】:2019-10-09 19:01:41
【问题描述】:

我正在寻找一种有效的方法来生成包含 7 个字符(字母、数字、特殊字符)的 500 万个唯一代码。

基本上,我的想法是生成一个具有唯一约束的表。然后生成一个代码,将它插入到数据库中,看看它是否被“接受”(意思是一个新代码),直到我们有 500 万个唯一代码。

另外,他们的想法是生成一个包含 500 万个唯一代码的数组,然后将它们立即插入数据库,以查看有多少代码进入数据库(是唯一的)。

第三种选择是创建一个代码,检查它是否已经存在,如果不将它插入到数据库中。

我现在的问题是我应该使用什么方法 - 我可能会监督一个问题。还是有更好的办法?

非常感谢!

【问题讨论】:

  • 你可以使用 uuid - en.wikipedia.org/wiki/Universally_unique_identifier。见碰撞块。并将其用作数据库中的唯一键
  • @myxaxa UUID 不是 7 位数字……
  • 代码必须满足哪些先决条件?因为如果没有,只需使用 0000001 - 5000000。
  • 其他解决方案:在插入之前按 1000 或 10000 或类似的方式创建和检查您的代码。将它们一一插入将花费数据库的时间。创建 500 万个需要一些内存,如果它在结束前崩溃,您将不得不重新启动所有作业。编程是妥协的结果。
  • @DoktorOSwaldo - 我们想使用数字、字母、特殊字符;大写和小写。

标签: php


【解决方案1】:

你想要的代码需要插入数据库吗?

最好不要不断地向数据库请求并尝试它是否是唯一的。

您可以先将代码存储到数组中,然后再将其放入数据库。

伪代码:

  1. 生成唯一的 500 万个代码,插入哈希表或数组中。 // 当你插入一个新的哈希表时,检查它是否存在。

  2. 然后您现在将这个哈希表或数组插入数据库中。

【讨论】:

    【解决方案2】:

    选择一个合适的函数来生成一个随机码;出于说明目的,我将使用这个:

    function generateCode() {
        return substr(bin2hex(random_bytes(4)), 0, 7);
    }
    

    请参阅https://stackoverflow.com/a/22829048/476 和其中的其他答案,以选择适合您的东西。重要的一点是它使用了良好的随机性来源random_bytesrandom_intopenssl_random_pseudo_bytes/dev/urandom。这最大限度地减少了对该函数的两次调用产生相同输出的机会。

    从那里,只需使用数组键对值进行重复数据删除:

    $codes = [];
    
    while (count($codes) < 5000000) {
        $codes[generateCode()] = null;
    }
    
    $codes = array_keys($codes);
    

    如果 generateCode 足够随机,则应该很少有冲突,并且以这种方式生成代码不应该有太多开销。即使这可能是一次性操作,效率也不是最重要的。 500 万个短字符串当然应该可以毫无问题地放入内存中。然后,您可以将它们全部插入到数据库中。

    【讨论】:

    • 那为什么不使用 Set 呢? $set = new \Ds\Set(); $set-&gt;add(generateCode); 每个定义都没有重复项。
    • 也很好,我承认我最近没有跟上 PHP 中可用的内容。
    • 啊抱歉,我必须承认我忘记它在扩展名(php-ds)中。
    【解决方案3】:
    function generateRandomString($length = 7) {
    
        // you can update these with new chars
        $characters = '!@#$%^&*()_+0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString = '';
        for ($i = 0; $i < $charactersLength; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    }
    

    现在使用一个数组来存储代码:

    $codes = array();
    while(count($codes)!=5000000){
       $code =  generateRandomString();
       $codes[$code] =  $code;
    }
    

    $codes 键和值,都具有相同的代码。

    【讨论】:

      【解决方案4】:

      鉴于您生成唯一标识符(作为难以猜测的优惠券代码)的目的,我想说您应该生成一个结合了“唯一”部分和“随机”部分的 unique identifier .

      • “唯一”部分可以是单调递增的计数器(例如支持数据库中自动递增的行号),它可以选择性地用作完整周期 linear congruential generator 的种子(在所有可能的情况下伪随机循环)重复之前的周期内的值)。
      • “随机”部分只是使用加密随机数生成器(PHP 为random_int)生成的随机数。一般来说,随机部分越长,它的可预测性就越差。

      此外,为了生成唯一的优惠券代码,没有理由将自己限制为 7 个字符的代码,尤其是在最终用户不需要直接输入这些代码的情况下。另见this question

      【讨论】:

        猜你喜欢
        • 2011-08-19
        • 1970-01-01
        • 2013-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-25
        • 2010-09-18
        • 2014-04-07
        相关资源
        最近更新 更多