生成可同时访问的唯一编号

Generate unique numbers with simultaneous access

情况: 人们会在我的系统上订票,我想生成票号。

该应用程序并不大,但已经可以正常工作了。后端完全用 vanilla php.

编写

但我一次只测试了一个用户。现在我猜可能会有几个用户同时访问机票订单,因为公司内部只有很短的时间window可以订购。

数据库 (MongoDB) 将每个事件保存为文档。每个文档都有一个字段,其中包含第一个免费票号。支付过程完成后,php 脚本会检查用户购买了多少张票,然后将开始生成票号(获取当前值 -> 增加 -> 将其保存到数据库 -> 等)。现在,当两个人同时执行此操作时,可能会发生这样的事情:双方都将获得 2314 作为当前可用数字,之后双方都会增加。现在有两张相同票号的票

我考虑更改为 sql 并获取插入行的 ID,因为这已经是一个唯一编号。我也想过取当前时间+salt然后hash一下(不过这样就会有残酷的票号)

但我想知道是否有可能在不使用 sql 中的数据库函数的情况下实现这一目标。我想这在其他情况下也可能有用,在其他情况下我可能无法使用 sql 之类的东西。我想到了诸如“阻止对 number/function 的访问”之类的事情,直到第一个调用函数再次释放它。

如果票号不必按特定顺序排列,您可以生成随机票号:

function generate_string($input, $strength = 10) {

$input_length = strlen($input);
$random_string = '';
for ($i = 0; $i < $strength; $i++) {
    $random_character = $input[random_int(0, $input_length - 1)];
    $random_string .= $random_character;
}

return $random_string;
}

例如

$input = '0123456789';

甚至

$input = '0123456789ABCDEF';

十六进制票号。

你可以使用 hrtime()

<?php
// hrtime
echo hrtime(true).PHP_EOL.
    hrtime(true).PHP_EOL.
    hrtime(true).PHP_EOL.
    hrtime(true).PHP_EOL.
    hrtime(true).PHP_EOL;
    
// microtime
echo microtime(true).PHP_EOL.
    microtime(true).PHP_EOL.
    microtime(true).PHP_EOL.
    microtime(true).PHP_EOL.
    microtime(true).PHP_EOL.
    microtime(true);

结果:

25558478919927842
25558478919929611
25558478919930289
25558478919930576
25558478919930779
1597318697.2849
1597318697.2849
1597318697.2849
1597318697.2849
1597318697.2849
1597318697.2849

以上相当于多个用户会同时访问票单。如您所见,microtime 是不够的。

但是您可以使用上面的最后 5 个数字,即 27842,并且很可能是唯一的。

除此之外,您可以将用户 ID 放在前面以获得更多熵。

如果您想要连续且 100% 防止重复,那么您唯一的选择是使用存储在数据库中的增量 ID。