如何优雅生成非递增的唯一的数字uid?

  • 生成8位长度数字UID
  • 非递增,无规律
  • 唯一性

目前想到的方案

  1. 提前生成一堆UID,随机抽取
  2. 写入UID前随机生成,判断是否存在

但这两种方案都需要提前查询下数据库,请问有没有效率更高的?

类似生成QQ号的算法?

阅读 7.3k
8 个回答

先生成一大堆uid 并标记status=0,然后sql 随机查询1条status=0的,使用并标记为status=1

可以Mysql数据库批量生产uid status为0 再存入redis 随机获取一个删除redis value 并更新 Mysql状态为1

可以参考雪花算法,但是雪花算法是64位,8位十进制数最大27位太短了
所以还是需要根据具体业务场景决定怎么做,需要考虑的问题包括但不限于:

  1. 并发多大?
  2. 服务部署多少个?

所以最简单有效的方法还是数据里先乱序存好这些id,然后随用随取。。。

我一开始也是想到了雪花算法,但是仔细想了想还是有很多不足,雪花算法虽然不重复,但是它根据时间戳就必然导致他是有递增趋势的,而且不是连续递增,就可能存在漏掉一些id。比如第一次生成10000000,第二次生成10000003,那中间的数就相当于丢了,而且这种算法在一秒内提供的id数量是有限的。用时间戳的话,因为99999999对应的二进制是101 1111 0101 1110 0000 1111 1111,如果生成的时间戳如果是全1的话,就有可能导致最终结果大于1亿。如果不在乎这些个问题,那确实可以用。

剩下的方式,感觉还是提前生成大量号码,存数据库。每次提取一批号码到内存中,效果和效率应该都还行。

新手上路,请多包涵

时间戳转16进制后加盐取md5?

新手上路,请多包涵

8 位数,千万级,用Bitmap 试试

MongoDB 的 ObjectID 实现

本身因为位数太少,不好保证唯一性,因为按现在计算机处理速度,就是在1秒以内,这么多UID也肯定用完的,这就有了冲突。

如果不建议冲突,其实有一种取巧的方法,大致思路是:

  1. 有一个每秒随机变化的数字值数组(10个数字字符,随机交换位置)A
  2. 循环计数增量0-99999999作为生成UID的源
  3. 把UID源每位用当前A的对应位替代来生成UID。

比如一个时候的A值是[0,1,2,3,4,5,6,7,8,9],则源UID值12345678对应的UID就是12345678,
但同样的源值,在A值为[0,9,8,7,6,5,4,3,2,1],时,对应的UID变成98765432了。
这个算法的好处是不需要查表(雪花算法需要查表比较),而且在一定时间内肯定可以保证唯一性(A不变情况下)

不过具体哪个算法更合适你,其实还要考虑真实的应用场景关键目的是什么,为什么需要这个数据(即这个数据到底是用来干什么的)

如果不是只能用数字字符,则8位字符串(排除一些相似字符比如0o1l之类),可用空间更多。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题