使用auto_increment生成PHP短唯一ID?

Dar*_*nke 7 php mysql unique auto-increment

我想生成一个简短的唯一ID,而不必检查冲突.

我目前做这样的事情,但我目前生成的ID是随机的,并且在循环中检查冲突是令人讨厌的,并且如果记录数量显着增加将会变得昂贵.

通常担心碰撞不是问题,但我想要生成的唯一ID是一个短的唯一字符串5-8个字符,字母数字,就像tinyurl一样.

编辑:我想从5个字符开始,如果我达到6000万条目,那么去6 ...等等.

为此,我想我可以使用对用户隐藏的auto_increment值,而是用一个MD5或其他方法来呈现它们以从中生成唯一的字符串.

生成的字符串看起来不应该是线性的,所以简单地将auto_incremented ID转换为base 36[0-9A-Z]有点过于简单了,但是这样的函数就是我要用的东西.

编辑:安全性不是问题,因为这不会用于保护信息.它只是更长字符串的快捷方式.谢谢.

感谢您的建议,抱歉延误.牙医..

Wim*_*Wim 6

你需要通过构造正确的东西,即置换函数:这是一个函数,它将一个整数(你的顺序计数器)的一对一可逆映射到另一个整数.一些例子(这些的任何组合也应该起作用):

  • 反转一些位(fi使用XOR,^在PHP中)
  • 交换位的位置(($ i&0xc)>> 2 |($ i&0x3)<< 2),或者只是颠倒所有位的顺序
  • 添加一个常数值以你的最大范围为模(如果你把它与上面的那个结合起来,必须是两倍)

示例:此函数将0,1,2,3,5,...转换为13,4,12,7,15,..,数字最多为15:

$i=($input+97) & 0xf;
$result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;
Run Code Online (Sandbox Code Playgroud)

编辑

一种更简单的方法是使用线性同余生成器(LCG,通常用于生成随机数),它由以下形式的公式定义:

X_n+1 = (a * X_n + c) mod m
Run Code Online (Sandbox Code Playgroud)

对于a,c和m的良好值,X_0,X_1 ... X_m-1的序列将包含0和m-1之间的所有数字恰好一次.现在,您可以从线性增加的索引开始,并使用LCG序列中的下一个值作为"秘密"键.

EDIT2

执行:你可以设计自己的LCG的参数,但如果你弄错了也不会覆盖全范围(因此有重复),所以我会用一个发布,并试图设置的参数从这里本文:

a = 16807, c = 0, m = 2147483647
Run Code Online (Sandbox Code Playgroud)

这给你一个2**31的范围.使用pack(),您可以将结果整数作为字符串,base64_encode()使其成为可读字符串(最多6个有效字符,每字节6位),因此这可能是您的函数:

substr(base64_encode(pack("l", (16807 * $index) % 2147483647)), 0, 6)
Run Code Online (Sandbox Code Playgroud)