8位随机代码

2 投票
8 回答
2868 浏览
提问于 2025-04-16 06:35

我看过一些在StackOverflow上问的类似问题的回答,但没找到我想要的。

有没有更有效的方法来生成8个字符的唯一ID,使用36进制(0-9和A-Z),而不是先生成一个唯一ID,然后去数据库查询看看这个ID是否已经存在,如果存在就再生成一个,直到找到一个没被用过的ID?

我找到的其他解决方案是用时间来生成ID,但这可能太容易被猜到,而且在分布式系统中可能效果不好。可以把这些ID看作是促销代码。

8 个回答

1

很遗憾,36进制的8位数字有点少。它最多只能生成200万亿个不同的ID,所以如果你随机生成140万个ID,碰撞的概率大约有一半。

你可以考虑使用一种周期很长的伪随机数生成器(PRNG),然后通过某种方式把它的当前状态映射到你的ID空间。比如说,使用一个41位的线性反馈移位寄存器(LFSR),虽然它不是完全安全的,但如果你保护的东西不是特别重要,这样做可能还算可以。你可以让不同的节点从不同的位置开始生成ID,这样就不需要每次都去访问数据库。

不过,任何这种确定性的方法都有个问题,就是一旦被破解,就完全不可信了,所有的ID都不能再信任。所以,从数据库中分配ID可能是更好的选择,可以一次分配一千个或者其他数量。

如果你的ID空间更大,那你就可以使用更安全的技术,比如ID可以包含一些标识来源的信息,一个递增的序列号,以及一个使用来源唯一密钥生成的HMAC。

10

一种方法是反过来做:在数据库里生成大量的内容,每当你需要的时候就生成,然后你可以在需要的时候从数据库里取出一个,或者为你的特定过程预留一大堆(也就是在数据库里标记它们为“可能会用到”),然后从内存中分配给需要的地方。

7

我觉得你说的“效率低下”的方法其实并不一定低效。想想看:

  • 总共有 36^8 = 2,821,109,907,456(大约 2.8 万亿)种可能的 ID。
  • 如果你已经有 N 个 ID,那么新生成的随机 ID 和已有 ID 重复的概率是 N 在大约 2.8 万亿中。
  • 除非 N 达到几百亿,否则你用“生成一个唯一 ID,然后查询数据库看它是否已经存在”的方法,几乎总是能在一次循环内完成。

只要设计得当,你应该能在一次数据库请求中生成一个保证唯一的 ID,几乎在所有情况下都是这样……除非你已有的 ID 数量非常庞大。(如果是这样,只需在 ID 后面加几个字符,这个问题就解决了。)

如果你愿意,可以通过批量生成 ID 来减少每个 ID 的平均数据库操作次数到少于一次,但这样可能会有一些复杂的问题,特别是如果你需要记录实际使用的 ID 数量的话。

不过,如果你最多只有 150,000 个 ID(我假设这些 ID 是在很长一段时间内生成的),那么批量创建 ID 就不值得去做……除非你是在进行大规模上传操作。

撰写回答