问题
我正在尝试向用户表添加一个12位长(仅限数值!)的唯一标识符,该标识符将被提供给用户以便用户相互查找。
因为它将被传递给用户,所以它需要与用户表上的自动增量id无关。
我想到的两种方法是:
- 循环直到获得唯一编号**
do {
// get a random 12 digit number
$identifier = str_pad(rand(0, 999999999999), 12, '0', STR_PAD_LEFT);
// check if it is unique
$exists = User::where('identifier', $identifier)->exists();
} while ($exists)
return $identifier
- 缺点**
从理论上讲,它可能会陷入无限循环(尽管几乎不可能)。
- 相应地调整随机数**
// get all the identifiers as array
$identifiers = User::orderBy('identifier')->pluck('identifier')->toArray();
// random number becomes lower depending on the total users
$my_identifier = rand(0, 999999999999 - count($identifiers));
// increment for all the smaller identifiers
foreach($identifiers as $identifier) {
if(intval($identifier) > $my_identifier) break;
$my_identifier ++;
}
return str_pad($my_identifier, 12, '0', STR_PAD_LEFT)
- 缺点**
虽然这确保了我不会陷入无限循环,但必须循环遍历一个数组,用户计数的长度听起来相当繁重。
问题
我认为这两个解决方案中最好的是第一个,因为无限循环的可能性基本上是不存在的,而第二个解决方案看起来真的很笨重和不切实际。
但是,有没有办法避免这两种解决方案的缺点呢?
3条答案
按热度按时间ukdjmx9f1#
可以使用UUID(通用唯一标识符)列。UUID是一个128位值,保证在时间和空间上唯一,因此适合生成唯一标识符。
您可以在用户表中创建UUID列,如下所示:
这将在用户表中添加一个名为“uuid”的新列。
要为每个用户生成UUID,可以使用MySQL中的UUID()函数:
您也可以使用uniqid()函数在PHP中生成UUID:
要确保UUID的长度为12位,可以使用substr()函数提取UUID的前12个字符:
ru9i0ody2#
您可以使用自动递增的数字,并通过某种算法创建相应的伪随机数,下面是一个示例:
自动递增的号码可以从另一个服务生成,结果是一一对应的,但不容易恢复。
pkln4tw63#
到目前为止,还没有一个答案来创建一个12位数的标识符,将是随机的,唯一的,"轻",并与用户ID无关。
然而,这个问题上的选项和shingo分享的选项都是完全可行的,在运行了一些测试之后,我的结论是我想得太多了。
在一天结束时,这些方法实际上都没有一个缺点,使他们不可行,你应该选择什么方法使用取决于你的要求。
循环直到我得到一个唯一的编号
| 有限回路|少量循环|与id无关|
| - ------|- ------|- ------|
| 没有|是的|是的|
假设在这个例子中我们有100000个用户。
一个新用户注册,我必须为该用户创建一个新标识符。
在1000000000个可用标识符中,只使用了100000个标识符,while循环循环一次的概率为1/10000。
此外,代码在成为问题之前必须循环数千次。
只有在大部分标识符已经被使用的情况下,这才可能成为一个问题。
您不应该****使用此方法为具有500000个用户的表提供6位标识符。
相应调整随机数
| 有限回路|少量循环|与id无关|
| - ------|- ------|- ------|
| 是的|没有|是的|
我在这段代码中遇到的问题是它"循环太多"。
如果我的表有100000个用户,那么它很容易循环100000次。
然而,在沙箱上测试了一些代码后,我得出结论,这么小的for循环可以在几毫秒内轻松地循环10万次,因此消除了任何关于代码成为性能杀手的担忧。
虽然循环这么多的想法仍然困扰着我,但我会判断这种方法是"最安全的"。
创建伪随机数
| 有限回路|少量循环|与id无关|
| - ------|- ------|- ------|
| 是的|什么事?|没有|
这是shingo提供的解决方案,这个方法的问题是与用户id的一一对应,这是我想避免的。
然而,如果你没有任何问题,这可能是最好的方法。
我认为这种方法还消除了在数据库中存储12位数字的需要,它允许您直接从12位数字代码中获取用户ID。