PHP-uniqid(“uniqid”)是生成唯一和顺序密钥服务器端的一个很好的实用解决方案吗?

PHP-uniqid(“uniqid”)是生成唯一和顺序密钥服务器端的一个很好的实用解决方案吗?,php,mysql,optimization,Php,Mysql,Optimization,全部, 我想在注册期间生成服务器端的用户id。此id应该是连续的,以允许集群索引。显然,它也需要独特 我可以在多大程度上使用uniqid(“”)?我不是在建立谷歌,我假设两个用户在同一微秒注册的风险接近于零——但我没有任何实际经验作为基础。SQL将拒绝重复的id,我可以在php代码中有一个循环,在发生冲突/数据输入失败的情况下继续发送新的注册条目,但如果冲突很少,这才是一个好方法 或者,我可以添加一个带有uniqid(“,TRUE)的随机邮政编码,但是如果两个用户在同一微秒内注册,则密钥不能再按

全部,

我想在注册期间生成服务器端的用户id。此id应该是连续的,以允许集群索引。显然,它也需要独特

我可以在多大程度上使用uniqid(“”)?我不是在建立谷歌,我假设两个用户在同一微秒注册的风险接近于零——但我没有任何实际经验作为基础。SQL将拒绝重复的id,我可以在php代码中有一个循环,在发生冲突/数据输入失败的情况下继续发送新的注册条目,但如果冲突很少,这才是一个好方法

或者,我可以添加一个带有
uniqid(“,TRUE)
的随机邮政编码,但是如果两个用户在同一微秒内注册,则密钥不能再按顺序排列

解决我的难题的最佳、实用的方法是什么?我是不是想得太多了

谢谢


JDelage

uniqid
只不过是的一个接口(这就是它生成顺序ID的原因),因此,它可以是可预测的,并且可以创建一个副本

此id应该是连续的,以允许集群索引。显然,它也需要独特。[…]我是不是想得太多了

大多数数据库,包括MySQL,都包含事务安全序列生成器,非常原始,但也很有效。auto inc主键可以确保唯一性,更重要的是,它并不奇怪


这就是说,确保表中的id列是主键是对重复id的完全防御。

我偏爱UUID。它不是一个递增的数字,应该始终是unqiue。但是,不要在INSERT语句中使用函数UUID。它可能会导致问题。

在数据库理论中,假设没有事件在同一时间发生,在你的例子中是微秒。许多数据库概念都建立在这一假设之上

我没有听到
uniqid
在顺序请求上生成相同的哈希。因为它的种子是微秒,而且处理器很可能在微秒内或多或少地执行一条机器指令,所以处理两个请求之间的时间太长(即使它们在单个CPU中同时运行)

如果您认为512位散列(32个十六进制字符)中可能存在冲突,那么您可以构建自己的摘要函数,该函数使用字母表和标点符号中的更多字符,因为正如我前面所说的,我们解决了时间种子问题,您应该担心的是充分利用种子并降低冲突概率

如果您想确定,您可以以互斥的方式为请求提供服务,然后在为请求提供服务之后,您可以向数据库插入一行(比如说用户注册,向用户表插入一条用户记录),并使用PHP函数
mysql\u insert\u id()
然后,您可以继续为其他请求提供服务,以便使用最近插入的记录id作为种子(对于任何两个连续请求,该id始终不同)

根据要求澄清最后一段: 正如我之前所说的,根据服务理论,数据库中不会同时发生任何事情。总是其中一个先发球。因此,您可以在数据库中启动事务。假设您正在注册一个新用户。您将说
插入用户(用户名、密码)值(?,)
。现在,您已经插入了一个新用户。当这个数据库查询发生时,您应该实现互斥锁(
mutex
),我不知道在PHP中是如何实现的。若您实现了互斥锁,第二个请求将等待您完成对第一个请求的处理。在数据库中插入行之后,您可以使用
$i=mysql\u insert\u id()
检索刚刚插入的行的id!当您对第二个用户的ID说
$i+1
时,它将是唯一的。因为第一个用户是
300
,那么第二个用户将是
301

事实上,数据库自动增量ID总是唯一的。如果您想为用户创建一个唯一的字符串哈希,这里有一个方法

  • 插入用户。(上述质询)
  • 使用
    $i=mysql\u insert\u id()获取用户id
  • 然后用一些摘要算法加密这个id,比如
    $d=strev(md5($i))
  • 然后将此值放在
    users
    表的
    unique\u id
    列上,其中id=$i查询为
    UPDATE user SET unique\u id='$d'
  • 好了,每个人都有自己独特的字符串
    我在uniqid()方面从来没有遇到过任何问题。如果您在代码中使用它,而不是让数据库来处理它,那么在涉及事务时,您就不能保证其正常运行。您需要担心锁定、死锁和回滚。如果让数据库替你处理,你就不必担心这些了。在数据库之外做自己的标识符是愚蠢的。相信我,我继承了一个代码库,它可以生成代码端标识符,处理由此产生的边缘案例是一场彻头彻尾的噩梦。所以你是说,一个额外的db调用的成本(因为我计划使用用户id作为散列pw的盐)被它以后消除的风险所抵消……这不是查询的成本,而是设计的成本。您必须获取下一个可用标识符,做一些工作,然后进行插入。如果另一个进程在同一时间运行,并且碰巧正在执行相同的操作,那么它可能会在插入时在您执行之前成功。这意味着插入将失败,并出现重复密钥错误,如果您在事务中,可以立即执行,也可以在提交时执行。然后,您的代码必须清理混乱,并尝试获取下一个id以进行另一次尝试