文档章节

PHP 的 uniqid 函数产生的 id 真的是唯一的么?

葬-花
 葬-花
发布于 05/30 14:52
字数 724
阅读 72
收藏 0

最近使用到了 uniqid,就产生了疑问?uniqid 生成的 id 由什么组成?真的是唯一的么?什么情况下会产生冲突?

从文档中看到 uniqid 函数有两个参数

uniqid 的结构

看源码:

PHP_FUNCTION(uniqid)
{
    ...
    gettimeofday((struct timeval *) &tv, (struct timezone *) NULL);
    sec = (int) tv.tv_sec;
    usec = (int) (tv.tv_usec % 0x100000);

    ...
    if (more_entropy) {
        uniqid = strpprintf(0, "%s%08x%05x%.8F", prefix, sec, usec, php_combined_lcg() * 10);
    } else {
        uniqid = strpprintf(0, "%s%08x%05x", prefix, sec, usec);
    }

    RETURN_STR(uniqid);
}

基本就了解清楚了。uniqid 是由四个部分组成:

prefix + sec + usec + “.” + php_combined_lcg

其中 prefix 就是 uniqid 函数的第一个参数。它是一个字符串,传递进来什么,就直接返回什么。

sec 是当前时钟的秒,usec 是毫秒,这两个值都是从 gettimeofday 获取的。换句话说,只要在一台机器上,两个 php 程序在同一个毫秒内获取的 sec 和 usec 是一样的。

php_combined_lcg 是 uniqid 的第二个参数决定的,它是一个墒值,它是使用线性同余生成一个 0 ~ 1 之间的随机数。如果第二个参数为 true,就有这个值,如果第二个参数为 false,就没有这个值。

比如:

➜  ~ php -r 'echo uniqid("my_", true);'
my_5afe9b414c2141.76621929

结论

所以说,如果我们单纯使用 uniqid() 这个方法,不带任何参数的话,这个方法只能保证单个进程,在同一个毫秒内是唯一的。如果使用uniqid("", true)。 带了一个墒值,自身已经有一个随机的方式能保证生成的id的随机性了。但是由于线性同余是比较简单的生成随机数的算法,随机性有可能还不够,所以,网上流传的一种更随机数值的方式是:

uniqid(mt_rand(), true)

其中 mt_rand() 生成随机数就不是使用线性同余生成随机数的方式了,而是使用 Mersenne Twister Random Number Generator (梅森旋转算法)。换句话说,上面这个 id 由两种随机算法 + 时间戳生成。基本上,这个算法在很大程度上能保证唯一性了(如果要问冲突率的话,估计只有数学系学生能研究出来了...)。

上面的这个给出的id会有一个点号,而且长度并不是128bit。如果希望生成uuid,就需要一个hash,不管是md5,sha1 都是可以选择的。所以网上又有一种生成唯一码的方式。

md5(uniqid(mt_rand(), true))

但是,本质上,这两种方式的随机性是相等的。

md5(uniqid(mt_rand(), true))--------亲证这个效果好,不会重,就是没规律----我自己的话

本文转载自:https://www.cnblogs.com/yjf512/p/9057229.html

葬-花
粉丝 2
博文 31
码字总数 5050
作品 0
西安
程序员
私信 提问
采用PHP函数uniqid生成一个唯一的ID

生成唯一ID的应用场景非常普遍,如临时缓存文件名称,临时变量,临时安全码等,uniqid()函数基于以微秒计的当前时间,生成一个唯一的 ID。由于生成唯一ID与微秒时间关联,因此ID的唯一性非常...

Minho
2012/02/08
2.6K
0
PHP利用共享内存构建计数器完成自增数值id生成 -- 适用于网页游戏携带区服号的数值id生成

我们之前的id生成是直接用的php的uniqid 存在的问题有: 1. 高并发下容易重复:当高并发适用uniqid来产生唯一id的时候,我的测试数据是:1000并发,每并发产生1000次,实际输出63万uid(可能...

鉴客
2010/12/16
559
1
PHP生成唯一订单号

在日常的网站开发中,我们经常需要生成唯一的订单号。订单号太短,在高迸发情况下,很容易造成订单号重复事件,虽然是小概率事件。 下面我们使用PHP多个函数生成一个现在最常用的订单号格式:...

豆花饭烧土豆
2016/03/15
308
0
PHP生成一个唯一订单号,年月日这种高大尚的例子

/生成一个订单号 function getOrderNum(){ $ordernumber = date('Ymd').substr(implode(NULL, arraymap('ord', strsplit(substr(uniqid(), 7, 13), 1))), 0, 8); return $ordernumber; } 简单......

15834278076
2018/11/12
35
0
再问订单号生成算法?

业务场景,高并发,多用户操作 使用microtime生成的时间戳生成唯一订单序列号,事实上高并发情况下有一定的重复几率,就连uniqid($more_entropy参数为false)函数生成的序列号都可能有重复的...

主编
2015/01/21
8K
18

没有更多内容

加载失败,请刷新页面

加载更多

Es问题汇总

1.索引类型为Date问题 "activitytime": { "type": "date", "format": "epoch_second"} 报错:message [ElasticsearchException[Elasticsearch exception [type=mapper_parsing_......

HLee
22分钟前
4
0
项目启动 spring 莫名 爆null 空指针异常,排查

项目之前跑起来运行好好的,结果 其他相关的模块更新代码之后,项目启动报错了 2019-12-06 08:55:13 [main] ERROR o.s.boot.SpringApplication - Application startup failedjava.lang.Nu...

之渊
23分钟前
7
0
人工智能如何快速入门?这10个开源AI项目真太香!

在过去的几年中,机器学习在许多行业中开辟了新的视野,出现了一些高级用例:Facebook的面部识别,Netflix推荐的电影,PrismaAI的图像样式转换,Siri的语音识别,Google Allo的自然语言处理,...

Gaikikii
31分钟前
5
0
电脑数据加密用什么软件好?深圳源代码数据加密软件工具那个好?风奥科技

企业文件加密对于企业发展的重要性?现在科学技术的发展,信息化进程的加密快,信息化产品以及融入生活与我们的日常生活息息相关!例如个人用户在日常的网购、以及通过一定的设备来获取新闻等...

fasoft
51分钟前
4
0
redis运行一段时间之后假死

现象:redis运行一段时间之后就会出现假死的现象 假死指的是:进程在、pid在、telnet 端口是通的、redis-cli命令可以连接,但无法查询数据,查询的时候报错,如下图: 可以看到这个报错是有关...

Jack088
53分钟前
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部