我需要生成唯一的 数字 ID。
那么,生成唯一 数字 ID的最佳方法是什么?
答案 0 :(得分:4)
没有什么能保证100%的独特性。
您需要了解与您需要的相比的独特性。
并使用任何algorythm并检查所有使用值列表中的每个值。
在编程领域,您需要的是pseudo random
数字。所以它的名字实际上解释了我的意思。
答案 1 :(得分:3)
数据库系统在创建诸如MySQL auto_increment
之类的数字时使用独占锁定,这些数字负责并发和许多其他复杂的细节。
您必须以同样的方式解决问题 - 从提供请求的PHP进程获取锁定,在某种持久存储中查找当前值,将其递增1,将其返回并释放锁。
最简单的方法是使用一个好的旧文件和独占锁定。
我将用一个类来说明( 应该>>调试,因为它不完整):
class MyAutoIncrement
{
protected $fh = null;
protected $file_path = '';
protected $auto_increment_offset = 1;
public function __construct($file_path, $offset = 1)
{
$this->file_path = $file_path;
$this->auto_increment_offset = $offset;
}
public function autoincrement()
{
if($this->acquire())
{
$current = (int)fread($this->fh);
$next += $this->auto_increment_offset;
fwrite($this->fh, $next);
$this->release();
return $next;
}
return null;
}
public function acquire()
{
$handler = $this->getFileHandler();
return flock($handler, LOCK_EX);
}
public function release($close = false)
{
$handler = $this->getFileHandler();
return flock($handler, LOCK_UN);
if($close)
{
fclose($handler);
$this->fh = null;
}
}
protected function acquireLock($handler)
{
return flock($handler, LOCK_EX);
}
protected function getFileHandler()
{
if(is_null($this->fh))
{
$this->fh = fopen($this->file_path, 'c+');
if($this->fh === false)
{
throw new \Exception(sprintf("Unable to open the specified file: %s", $this->file_path));
}
}
return $this->fh;
}
}
用法:
$ai = new MyAutoIncrement('/path/to/counter/file.txt');
try
{
$id = $ai->autoincrement();
if(!is_null($id))
{
// Voila, you got your number, do stuff
}
else
{
// We went wrong somewhere
}
}
catch(\Exception $e)
{
// Something went wrong
}
答案 2 :(得分:1)
如前所述。没有什么能保证100%的独特性。
虽然这将是相当独特的:)
$iUniqueNumber = crc32(uniqid());
答案 3 :(得分:1)
您可以结合使用time()和getmypid()来获取所需内容 - 数字唯一ID。您可以在给定时间启动多个php进程,但它们在给定时间永远不会具有相同的进程ID(除非服务器进程计数器在不到一秒的时间内重叠,这在kernel.pid_max
设置时几乎是不可能的正确地)。
<?
function getUniqueID() {
return time() . '.' . getmypid();
}
?>
该功能将为每个服务器生成一个唯一ID 每个脚本执行。如果您在同一个脚本中多次调用它并且希望它每次都返回唯一值,它将失败。在这种情况下,您可以在函数体内定义一些static
变量来跟踪它。
答案 4 :(得分:0)
您可以制作自己的增量值,以保证100%的唯一性,而无需使用沉重的算法:
会话唯一ID:
session_start();
$_SESSION['increment'] = 5;//i fix 5 but you need to get it in bdd,xml,...
function get_new_id(){
$_SESSION['increment']++;
//store new value of increment
return $_SESSION['increment'];
}
$my_unique_id = get_new_id();
echo $my_unique_id;
全球唯一ID(不要使用此!):
function get_new_id(){
$increment = file_get_contents('increment.txt');
$increment++;
file_put_contents('increment.txt', $increment);
return $increment;
}
$my_unique_id = get_new_id();
echo $my_unique_id;
答案 5 :(得分:0)
你谈到了时间,microtime怎么样?
即使您连续创建两个数字,您也会得到不同的值。你当然需要玩一点才能使它成为一个独特的整数,但它应该能够提供帮助。
答案 6 :(得分:0)
function getserial()
{
$fn='/where_you_want/serial.dat';
$fp = fopen($fn, "r+");
if (flock($fp, LOCK_EX)) { $serial=fgets($fp);$serial++; }
else
{ print('lock error, ABORT'); exit; }
$h=fopen($fn.'.tmp','w'); fwrite($h,$serial);fclose($h);
if (filesize($fn.'.tmp')>0)
{
system('rm -f '.$fn.'.tmp');
fseek ($fp, 0);
fwrite($fp,$serial);
}
flock($fp, LOCK_UN); fclose($fp); @chmod($fn,0777);
return $serial;
}
此示例将为您提供唯一的序列号,在此之后,您可以确定它只存在一个实例。 请注意,为避免数据损坏,您必须先创建文件并先输入数字。 (例如,在没有输入或其他任何内容的情况下写1)
这是一个非常简单的功能,但现在它已经为我工作了10多年......
答案 7 :(得分:-1)
我建议将PHP进程ID与microtime(true)连接起来,以增加具有唯一值的可能性。