【发布时间】:2017-04-02 08:42:33
【问题描述】:
我想创建一个固定长度的随机字符串(在我的用例中为 8 个字符),并且生成的字符串必须区分大小写并且在黑名单中是唯一的。我知道这听起来像一个 UUID,但我有一个特定要求阻止我使用它们
- 不允许使用某些字符,即 I、l 和 1 相似,O 和 0 也是如此
我最初的实现是可靠的并且解决了任务,但表现不佳。我所说的糟糕是指它注定每天都会越来越慢。
这是我要优化的当前实现:
private function uuid()
{
$chars = 'ABCDEFGHJKLMNPQRSTVUWXYZabcdefghijkmnopqrstvuwxyz23456789';
$uuid = null;
while (true) {
$uuid = substr(str_shuffle($chars), 0, 8);
if (null === DB::table('codes')->select('id')->whereRaw('BINARY uuid = ?', [$uuid])->first())) {
break;
}
}
return $uuid;
}
请不要批评我,我们生活在一个敏捷的世界中,这个实现是功能性的并且可以快速编码。
只需少量数据,它就可以很好地工作。但是,如果我在黑名单中有 1000 万个条目并尝试再创建 1000 个条目,它会失败,因为它需要 30 多分钟。
一个真正的用例是在数据库中有 10+ 百万个条目并尝试创建 20,000 个新的唯一代码。
我正在考虑预先播种所有允许的值,但这太疯狂了: (24+24+8)^8 = 9.6717312e+13
如果社区可以为我指明正确的方向,那就太好了。
最好, 尼古拉
【问题讨论】:
-
它是否需要不可预测/不可猜测?您不能简单地使用递增计数器的原因是什么?
-
不幸的是,它必须是不可预测的。想想优惠券代码。
标签: random unique uuid blacklist