[菜鸡随笔-4]分布式全局唯一ID生成方案之snowflake算法

 

已有的方案:

可大致分为:

  1. 完全依赖关系/非关系型数据库递增的方案
  2. 完全不依赖数据源作为生成因子的UUID
  3. 半依赖数据源作为生成因子的snowflake

 

 

为什么推荐snowflake?

这个问题,可以从前两个方案的缺点来讲。

 

  • 完全依赖关系/非关系型数据库递增的方案:

关系/非关系的区别细节就不展开了,只说说关系型。它最大的缺点是并发的瓶颈,其次是拓展性的问题,再就是还需要考虑数据库的可用性。

噢对了高可用也挺难搞的,不是说难度哈,只是这玩意是真滴麻烦啊,因为一般来说也得双写部署,不然挂掉一个master怎么办,对吧?那双写之后还需要给master配上中间件吧?噢中间件也需要高可用吧?好吧那最后还需要上个nginx或者keepalived…到了这里回头一看“完了我只想生成一个ID而已为什么还要增加那么多东西,需要额外考虑那么多东西?真蛋疼”。所以毙掉这个方案!

 

  • UUID

UUID,神奇的东西(我没仔细研究,所以用“神奇”这个词来蒙混过去),无需数据源作为生成因子却能生成全球唯一ID。屌哇!但是用它作为ID的话还是太大了,16个字节啊,浪费空间不说还影响索引的效率。

不过最大的缺点还不是它的大小,而是它是生成的ID是无序的,但是主流的数据库的索引数据结构都是B+树结构,所以你明白了吧。(这里不懂的朋友请自行搜索 B+树分裂问题 ,我没有能力在三言两语内解释清楚)

 

 

所以什么是snowflake?

snowflake 算法是 twitter 开源的分布式 id 生成算法,采用 Scala 语言实现,是把一个 64 位的 long 型的 id,1 个 bit 是不用的,用其中的 41 bits 作为毫秒数,用 10 bits 作为工作机器 id,12 bits 作为序列号。(这句话是复制来的)

 

  • snowflake算法生成的ID的结构:

0

00000000000000000000000000000000000000000

00000

00000

000000000000

符号位(1bit)

时间戳(41bit)

区域ID(5bit)

机器ID(5bit)

序列号(12bit)

       总共64bit,刚好是一个long类型的大小

属性说明:

符号位:符号位是不用的,因为ID只考虑正数。

时间戳:注意是精度为毫秒级的,而不是秒级的。

区域ID:也叫数据中心ID,标识机器所属的数据中心。

机器ID:配合区域ID,用作定位某区域的机房里的其中一台机器。

序列号:看到这里你可能已经明白了,时间戳标记了时间,区域和机器ID标记了机器所属,那么在一个时间单位里,同一台机器请求多个ID怎么办?对,所以需要序列号的递增作为ID的递增生成因子。

 

  • 算法思路:

如果是在同一时间单位内,则递增序列号作为ID生成因子,直至0 ~ 2^12-1 (0到4095)所有数字用完了,或者检测到时间戳更新了的时候,才将序列号归零重新递增。按照这个思路就可以做出理论上并发为 (2^12-1)(2^10)≈4,200,000 的ID生成算法了。很简单吧。我感觉就并发能力而言,这个算法可以用到死了。

(注意,区域/机器ID不是由snowflake生成的,而是让各个机器在需要时主动调用该生成算法,在调用时传入区域/机器ID作为分布式全局唯一ID的生成因子之一。)

 

 

算法的实现

 

 

 

 

 

测试结果

 

我的机器性能不足,加上目前只是单线程测试,所以你会看到图一开头就几个sequenceID都是0,那是因为时间戳更新后sequenceID归零了。

图二可以看到,单位时间内我机子的性能最多叠加到29。改天再做个多线程测试。完

 

 

5/26补上的多线程测试:

测试了半个小时发现还是按cpu核数开对应线程数效率最高。(话说网易云音乐占用cpu资源真严重,听着歌ID最多叠加到两百多而已)

不过遗憾的是机子性能真的很有限,ID最多叠加3.7k,到2^12-1还差那么几百就是上不去。。。

 

不过还是可以改一下sequenceID上限,以验证这个算法在序列号递增溢出的时候的正确性。

 

改成2^10-1,测试结果正常。完事

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值