您现在的位置是:首页 > 其他

李清波 2020-06-03 其他 1189 复制当前网址

uniqid



PHP uniqid() 函数

定义和用法

uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID。


语法

uniqid(prefix,more_entropy)


参数描述
prefix可选。为 ID 规定前缀。如果两个脚本在相同的微妙生成 ID,该参数很有用。
more_entropy可选。规定位于返回值末尾的更多的熵。


说明

如果 prefix 参数为空,则返回的字符串有 13 个字符串长。如果 more_entropy 参数设置为 true,则是 23 个字符串长。

如果 more_entropy 参数设置为 true,则在返回值的末尾添加额外的熵(使用组合线形同余数生成程序),这样可以结果的唯一性更好。


返回值

以字符串的形式返回唯一标识符。


提示和注释

注释:由于基于系统时间,通过该函数生成的 ID 不是最佳的。如需生成绝对唯一的 ID,请使用 md5() 函数(请在字符串函数参考中查找)。


例子

<?php
echo uniqid();
?>

输出类似:

4415297e3af8c


源码:

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))

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


文章来源:https://www.liqingbo.cn/blog-942.html

上一篇:unpack

下一篇:time_sleep_until

评论