我希望在不检查冲突的情况下生成一个简短的、唯一的ID。
我目前正在做这样的事情,但是我当前生成的ID是随机的,并且检查循环中的冲突是令人讨厌的,并且如果记录数量显着增加,将会变得非常昂贵。
通常担心冲突不是问题,但我想生成的唯一ID是一个5-8个字符的唯一字符串,字母数字,就像tinyurl一样。
编辑:我想从5个字符开始,如果我达到6000万个条目,那么就转到6..以此类推。
为此,我想我可以使用一个对用户隐藏的auto_increment值,并向他们提供一个MD5或其他方法来从该值生成一个惟一的字符串。
生成的字符串不应该看起来是线性的,所以简单地将auto_incremented ID转换为base 36 0-9A-Z有点过于简单,但我将使用类似这样的函数。
编辑:安全性不是问题,因为这不会用于保护信息。它只是一个更长字符串的快捷方式。谢谢。
谢谢您的建议,很抱歉让您久等了。牙医。
发布于 2009-10-31 00:39:08
您需要一些通过构造正确的东西,即置换函数:这是一个将一个整数(您的顺序计数器)一对一地可逆映射到另一个整数的函数。一些示例(这些示例的任意组合也应该有效):
示例:此函数将转换0、1、2、3、5、..变成13,4,12,7,15,..对于不超过15的数字:
$i=($input+97) & 0xf;
$result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;编辑
一种更简单的方法是使用线性同余生成器(LCG,通常用于生成随机数),它由以下形式的公式定义:
X_n+1 = (a * X_n + c) mod m对于a,c和m的good values,X_0,X_1的序列。X_m-1将恰好包含0到m-1之间的所有数字一次。现在,您可以从线性递增的索引开始,并使用LCG序列中的下一个值作为您的“秘密”密钥。
EDIT2
实现:您可以使用design your own LCG parameters,但是如果您弄错了,它将无法覆盖整个范围(因此会有重复的内容),所以我将在这里使用this paper中发布并试用过的一组参数
a = 16807, c = 0, m = 2147483647这为您提供了2**31的范围。使用pack()可以获得字符串形式的整数,base64_encode()使其成为可读的字符串(最多6个有效字符,每个字节6位),因此这可以是您的函数:
substr(base64_encode(pack("l", (16807 * $index) % 2147483647)), 0, 6)发布于 2009-10-30 22:50:55
您可能会生成当前日期时间/随机数的MD5散列,并将其截断为所需的长度(5-8个字符),然后将其存储为id字段。
如果您正在使用将此信息存储在数据库中,则不需要使用for循环来执行冲突检查,而只需执行一条select语句-类似于
SELECT count(1) c FROM Table WHERE id = :id其中:id是新生成的id。如果c大于0,那么你知道它已经存在了。
编辑
这可能不是最好的方法。但我会试一试,所以我猜你需要的是将一个数字转换成一个唯一的短字符串的方法,这是不按顺序的。
我猜就像你说的,base64编码已经完成了数字到短字符串的转换。为了避免序列问题,您可以在自动生成的id与某个“随机”值之间建立某种映射(唯一映射)。然后,您可以对这个唯一值进行base64编码。
您可以按如下方式生成此映射。使用临时表存储1- 10,000,000之间的值。按随机顺序对其进行排序,并将其存储到Map表中。
INSERT INTO MappingTable (mappedId) SELECT values FROM TemporaryTable ORDER BY RAND()其中,MappingTable有两个字段id (您的自动生成的id将根据它进行查找)和mappedId (您将为其生成base64编码)。
当您接近10,000,000时,您可以再次运行上面的代码,并将临时表中的值更改为10,000,001-20,000,000或类似的值。
发布于 2009-10-31 02:23:36
您可以使用逐位XOR来对一些位进行加扰:
select thefield ^ 377 from thetable;
+-----+---------+
| a | a ^ 377 |
+-----+---------+
| 154 | 483 |
| 152 | 481 |
| 69 | 316 |
| 35 | 346 |
| 72 | 305 |
| 139 | 498 |
| 96 | 281 |
| 31 | 358 |
| 11 | 370 |
| 127 | 262 |
+-----+---------+https://stackoverflow.com/questions/1650185
复制相似问题