唯一性id生成规则研究

不管我们用什么方法生成的id,都应该满足以下几个条件:

第一 ,  必须是唯一,可以全局唯一,或者同一种业务内唯一也可以。

第二, 必须按时间递增(这个需要解释吗)。

第三,尽量使用数字类型的,其次才考虑字符串型的。原因很简单,数字不需要使用编码(utf-8,gbk等)翻译。直接可以保存到数据库,而字符串必须使用编码翻译后才能使用。

第四, 在id里面尽量能看出id是什么时候生成的。

 

关于唯一性id生成讨论几种方案:

第一种,首选方案,数据库id自动生成,理由是没有任何难度,大家都会用。但是这只能在前期使用,

       (1) 当系统负载大了,数据库性能下降就会考虑更换别的方法了。

       (2) 如果有分库分表的话,也是不能用了,需要想别的办法替代。

第二种, uuid。

这个方案只能说可以用,能保证唯一 ,用起来简单,但是用了之后处理有点麻烦,因为不能按时间递增生成,保存到数据库的时候对数据库的性能有影响,至少主键索引如果是btree的话,肯定会有影响,不过可以把数据库主键索引改成hash,具体没有测试过,按理来说应该是会影响比较小了。有谁测试过了可以留言说下效果。

第三种,redis。

Redis是单线程的,所以也可以用来生成全局唯一的ID,利用redis对数字的原子自增操作(Redis的 INCR和INCRBY)。

第四种, twitter的snowflake。

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看https://github.com/twitter/snowflake

这种方法可以保证生成唯一,递增,数字型的id, 唯一的问题就是生成的id直接看不出是什么时候生成的。

 

第五种, snowflake 变种。

 (1)  因为long型的十进制只有19位长度,如果我们要数字型的,又要递增,又要能从id里面看出时间,就只有下面这种方法了。

年2位    月2位    日2位    时分4位  数据中心id2位机器id2位   取纳秒的最后5位 
1801011113121512345 

这种方法有一定问题,会有重复的id,因为long型长度的限制,我们时间只能精确到分钟,一分钟有60秒,就是60000毫秒, 然后我们的最后5位最多只有10万个数。如果同一台机器有在同一毫秒内生成多个的话,就可能会出现重复的了。 不过这应该能满足多数需求了。请求量不多的话,这完全够用了。

( 2 )    很多时候,19位长度不够使用,要超过19长度,我们就只有用字符串来实现了。字符串就比较方便了,可以任意生成满足我们需要的id或者订单号了。

年月日时分秒毫秒最后3位纳秒最后6位数据中心id2位机器id2位扩展id扩展id
1801011213158765325241022  

这种方法除了不是数字型的id,几乎没有别的缺点了,甚至还可以再加几位表示具体的服务的id到里面。可以自由扩展,甚至想加具体的业务id都可以。

1801011213158765325241022  最后大概是像这样的。每毫秒钟可以生成十万个不同的id

 

转载于:https://my.oschina.net/u/3770578/blog/1634456

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值