Random 针对黑名单的随机唯一字符串
我想创建一个固定长度的随机字符串(在我的用例中是8个字符),生成的字符串必须区分大小写,并且在黑名单中是唯一的。我知道这听起来像UUID,但我有一个特定的要求,阻止我使用它们Random 针对黑名单的随机唯一字符串,random,unique,uuid,blacklist,Random,Unique,Uuid,Blacklist,我想创建一个固定长度的随机字符串(在我的用例中是8个字符),生成的字符串必须区分大小写,并且在黑名单中是唯一的。我知道这听起来像UUID,但我有一个特定的要求,阻止我使用它们 有些字符是不允许的,即i、l和1是相似的,O和0也是相似的 我最初的实现是可靠的,解决了任务,但执行得很差。我所说的糟糕是指它注定每天都会越来越慢 这是我当前要优化的实现: private function uuid() { $chars = 'ABCDEFGHJKLMNPQRSTVUWXYZabcdefghijk
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多分钟
一个真正的用例是在数据库中有1000多万个条目,并尝试创建20000个新的唯一代码
我想预先设定所有允许的值,但这太疯狂了:
(24+24+8)^8=9.6717312e+13
如果社区能为我指明正确的方向,那就太好了
最好的,
尼古拉有两种选择:
s = "This is a string that uniquely identifies voucher #1. Blah blah."
h = hash(s)
guid = truncate(hash)
u = Db.GetIncrementingCounter()
p = Random.GetCharacters(3)
guid = u + p
我最终修改了方法:不再检查每个循环上是否存在uuid,例如50K DB检查,而是将生成的代码拆分为1000个代码的多个块,并在事务中发出INSERT IGNORE批处理查询
如果受影响的行数与项目数相同(本例中为1000),我知道没有冲突,我可以提交事务。否则,我需要回滚块并生成另外1000个代码。它是否需要不可预测/不可用?为什么不能简单地使用递增计数器?不幸的是,它必须是不可预测的。想想凭证代码。你知道输出区分大小写的哈希吗?我脑子里想不出什么。然而,您的回答让我想到了两个想法:1)将RDBS表从uuid的一列拆分为3列或更多列。目标是通过使用更细粒度的WHERE子句来加速DB检查。2) 尝试使用NoSQL存储和检查黑名单。今天晚些时候我两个都要试试。