唯一性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位  
18 01 01 1113 12 15 12345  

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

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

年月日 时分秒 毫秒最后3位 纳秒最后6位 数据中心id2位 机器id2位 扩展id 扩展id
180101 121315 876 532524 10 22    

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

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

猜你喜欢

转载自my.oschina.net/u/3770578/blog/1634456
今日推荐