2016-05-19 11:12:08 0 评论 PHP Boy.Lee

php生成100%不重复随机字符串实现方法

在日常php web开发中经常会用到随机字符串, 我们用随机字符串的目的很大程度上是为了不重复, 本文就结合我的实际经验来分析下, 如何实现100%不重复随机字符串.

 

{ 随机字符串分类 }

a. 一定概率不重复的随机字符串
b. 100%不会重复的随机字符串

 

{ a. 一定概率不重复的随机字符串 }

举一个经典的实现方法:

$seed = [];
$seed['time'] = time();
$seed['ip'] = Yii::app()->request->userHostAddress; //get ip address in Yii
$seed['randNum'] = mt_rand(10000, 99999);
$randString = implode('_', $seed); 

echo $randString;//1463624229_127.0.0.1_41111

上面的算法实现原理是利用unixtimestamp+ip address把前置条件限定在一秒内, 针对单个ip地址. 然后通过10000-99999的90000个随机数来控制随机概率

一秒 + 单个ip + 1/90000的概率, 针对用户量不太大的小型系统已经足够用了, 值得说明的是上述实现方法和UUID之类没有本质差别, 只是为了方便阅读

但是, 如果放眼RESTful架构中, 一个100台server的集群里, 那么问题就不一样了.

如果用户A ip一秒可以发起10k次请求, 我们基本就可以认为上述方法已经无法有效的生成非重复字符串了

 

{ b. 100%不重复的随机字符串 }

其实b比a简单, 有时候只是我们认为的把一些事情想复杂了.

稍微放低一点要求来想: 1, 2, 3, 4 不就是4个不重复的字符串吗?

什么要有一定的长度和不那么容易看出来?

那就通过md5(1), 来实现就可以了

具体实现php代码如下:

$topic = new Topic();
//TODO add necessary attributes

if ($topic->save()) {
    $randString = md5($topic->t_id);
    
    echo $randString;//c20ad4d76fe97759aa27a0c99bff6710
}else{
    //save fail, do sth
}

说明, 中间用的是MySQL之类的数据库, 通过自增PK来实现+1, 然后变化到一定长度这里用的是md5, 其他方法亦可

在对精度要求高并比较复杂的情况下, 牺牲一次简单数据库操作或者类似方式来获取100%不重复的字符串, 在性能和可靠性的权衡上是可取的

当然这只是一个思路希望能够抛砖引玉. 欢迎有想法的留言.