这样实时生成的ID唯一性有保证吗?
发布于 6 年前 作者 lightgm 4481 次浏览 来自 问答

在服务端需要即时生成一个类似UUID的ID号,为了能够为记录快速排序,我没有采用真的UUID,而是打算使用“系统当前时间戳”+“i”( i 是一个范围从1到9999的自增变量)拼接成一个新的整数作为ID,因为JavaScript正常是单线程的(如果采取多线程,我会将不同线程的i的取值范围错开),在单线程高并发(每秒小于i的最大值)请求ID号的情况下,应该是能够保证ID的唯一性的,请问我的这个方案有什么问题吗?

14 回复

不好说。 直接就用UUID做为id,另加一个时间用来排序不行吗? 或者用redis来生成id吧,直接incr能保证唯一

这种方法不太好,原因是

  • 冗余,生成的序列前面部分都是相同的
  • 没办法保证绝对唯一
  • 不易于扩展,如果做负载均衡,这部分代码就要改

优化建议

  • Redis Incr命令
  • Zookeeper有序节点

我们就是采用的这个方案 现在单进程没啥问题啊 但是也有缺点 之所以不用redis 或 其他的Zookeeper 数据库之类的 就是省事。如果你不需要递增序列的话 还是可以的。

@imhered 你说的第一个方案应该是比较省(容)事(易)靠(抄)谱(袭)的,redis了解过但是没用过,不知道为了生成这个id需要多大代价。

@lightgm 你要说抄袭或者省事也对,选择redis即省事又省时,还不会出错,为什么不可以选择呢?

redis不能就是基于内存的,速度很快。

至于你说的代价是代码实现上么?很简单,安装一个redis,只需要几行代码就可以完成你上面的需求了

@sunkuo 1.冗余的那几位数我觉得应该对性能和存储空间造成不了很大影响,我用的mongoDB 2.我就是特别想知道怎么没办法保证唯一?? 3.扩展的话估计需求不大,设计这个id是用来标识行业内部通讯系统的msg记录的,即便是以后大规模全面应用,最多把9999再加几位数,然后划分成几个区间,分给每个cluster,每个cluster在自己分配的区间内循环使用,也不至于重复啊 各位都推荐redis,redis我记得是单线程,cluster也刚刚引入没多久,是不是也不适合扩展和负载均衡? 补充:刚才查了一下,redis确实是支持分布式的

@imhered redis比uuid方案还要快?

@ipengyo 🤝原来我不是一个人😝

@lightgm 比不比uuid快我不知道,但是完全基于内存的啊。 很多秒杀系统的锁都是基于redis的,完全没问题啊

uuid学mongodb,由这几部分组成: 1.主机名 2.进程号 3.时间戳 4.自增长int 一个十几位的16进制数就能搞定

@aojiaotage 昨天用了这个方案,后来发现i用4位数再加上4位数的pid导致超过了js的int精度,这还没算上主机名………………如果用纯数字的字符串,是不是索引速度会比数字差很多?

@lightgm Number.MAX_SAFE_INTEGER 最大2^53 > 16^12, 也就是说12位以内的16进制数应该都是可以的哇,而且这还只是指计算和比较大小 可以用更高位的,这么大的数不够用嘛? 另外索引用字符串,但是hash算法完全可以是基于int嘛,不会多慢的

@lightgm 我们讨论的是更优,这其中包括扩展性、鲁棒性、并发性能。 你想飞天,可以造一个火箭,也可以做热气器,你非要说热气球可以,那你可以一直用热气球。 行业有很多更优秀的解决方案,你要做的是学习。我相信没有任何一家成熟公司用你的解决方案

使用redis的lua

  毫秒数  序列 预留 标识  机房  redis实例  共
  41     10   1   2     6    4         64 
回到顶部