需求:
function genRandomString($len, $t = 0)
{
$chars = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "2", "3", "4", "5", "6", "7", "8", "9");
$chars1 = array("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
$chars2 = array("1", "2", "0", "3", "4", "5", "6", "7", "8", "9");
$chars3 = array("A", "B", "C", "D", "E", "F", "G", "O", "H", "I", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z");
if ($t == 1) {
$charsLen = count($chars1) - 1;
shuffle($chars1);
$output = "";
for ($i = 0; $i < $len; $i++) {
$output .= $chars1[mt_rand(0, $charsLen)];
}
}
else if ($t == 2) {
$charsLen = count($chars2) - 1;
shuffle($chars2);
$output = "";
for ($i = 0; $i < $len; $i++) {
$output .= $chars2[mt_rand(0, $charsLen)];
}
}
else if ($t == 3) {
$charsLen = count($chars3) - 1;
shuffle($chars3);
$output = "";
for ($i = 0; $i < $len; $i++) {
$output .= $chars3[mt_rand(0, $charsLen)];
}
}
else {
$charsLen = count($chars) - 1;
shuffle($chars);
$output = "";
for ($i = 0; $i < $len; $i++) {
$output .= $chars[mt_rand(0, $charsLen)];
}
}
return $output;
}
基本就是金刚葫芦娃,一股脑生成,插入数据库。连判断都没有。虽然重复的概率小,但还是有可能呀。怎么做到一个优秀一点的?
有没有更好的方法?
是防伪码呀 >_<
1
ryd994 2018-03-23 10:11:51 +08:00 via Android
验证码这种使用场景,难道不该上 redis 么?重启就重启,反正丢几个验证码有没什么大事,用户只会怀疑自己打错了
|
2
arron 2018-03-23 10:28:28 +08:00
如果是批量,你就加两个干扰项:time, index 至于放进去怎么变化看需求,可以保证你生成的字符串不会重复。如果是用的时候再生成,那么 time + rand 基本就可以了,保证重复概率低。
|
3
whileFalse 2018-03-23 11:08:44 +08:00
uuid 不行吗
|
4
oott123 2018-03-23 11:41:17 +08:00 via Android
数据库做个唯一性索引,插崩了就重新插一下
|
5
loveCoding 2018-03-23 11:53:43 +08:00
生成的防伪码长度大概在 12~18 位
有可能是纯数字,或者字母+数字 楼上说的 uuid 满足需求的 |
6
DavidNineRoc OP @ryd994 不是验证码,是防伪码 >_<
@arron 真的不是验证码,是防伪码 @whileFalse 给客户使用的,就是验证是否是正品的防伪码 @oott123 这个,每次都插入,不如我的第二个方法 * 我想的就只是插入的时候返回 0 或者 1,循环结束计算返回 1 的集合,是否等于要生成的防伪码数量,如果不等于,(这时候,数量级已经下降了很多) * 来一个死循环,一次生成一个插入数据库,知道成功的条数弥补上一次重复的数量,跳出循环。 @loveCoding uuid 肯定不符合要求,长度太长,而且总是英文数字混合的。想要纯数字根本不可能 |
7
prolic 2018-03-23 13:12:45 +08:00 via Android
这需求数字加盐散列不就够了么,信不过 md5 你可以再去一次重
|
8
rrfeng 2018-03-23 13:15:26 +08:00 via Android
防伪:
发出去的存起来 算法自验证 楼上都在说什么... |
9
DavidNineRoc OP |
10
l12ab 2018-03-23 16:30:53 +08:00 via iPhone
类似于卖软件的生成序列号
|
11
LukeChien 2018-03-23 19:56:51 +08:00 via Android
时间戳+aes(时间戳,秘钥)
|
12
chinvo 2018-03-23 19:59:41 +08:00
Sonyflake-like 的串号,加上校验位
|
13
DavidNineRoc OP |
14
chinvo 2018-03-23 23:19:44 +08:00
|
15
DavidNineRoc OP @chinvo 看 $chars3,时间戳都有十位了,再加自增?一次生成十万百万级别的,基本就出现重复了
|
16
xml123 2018-03-24 09:25:03 +08:00 via Android
时间戳是唯一的,就算占了全部的位数,也不会重复啊
|
17
DavidNineRoc OP @xml123 你还年轻,来点并发,就会重复了
|