基于业务对Twitter生成全局唯一ID的SnowFlake算法的改造

1.需求来源:
公司现有评论系统的所有评论ID,是根据MySQL数据库的自增方式获得。随着时间的推移,唯一的MySQL后台库承受着大量的记录(大约在2亿左右),这样每次为了获得评论ID,而进行插入查找,效率变得低下。同时根据PHP业务开发组的反馈,多个已经开发和正在开发的生产系统中都需要用到ID生成服务,为了响应这些需求,我们决定开发一个公共的ID生成服务。
2.调研方法:
有了需求,就该着手调研。由于本人有些崇洋媚外,所以调研先从国外牛逼的大公司开始,发现Facebook,Twitter,Instagram,flickr等公司都开源了一些这样的算法,其中有的部分利用了数据库,有的利用精确到毫秒的时间,总之八仙过海,各显神通!(本人已经简单整理了这些文档,有机会跟大家分享)哈哈,最终选了一个最大牌的算法,那就是Twitter的SnowFlake算法(其实选它主要还是因为算法本身设计不依赖数据库)
3.算法简介:
现在有请我们的大牌明星登场!https://github.com/twitter/snowflake
Snowflake是twitter开源的一款独立的适用于分布式环境的ID生成算法。
生成的ID是64Bits整型数,同时满足高性能(>10K ids/s),低延迟(<2ms)和高可用。


基于业务对Twitter生成全局唯一ID的SnowFlake算法的改造
文章图片



1. 41位的时间序列(精确到毫秒,41位的长度可以使用69年)
2. 10位的机器标识(10位的长度最多支持部署1024个节点,支持多机房的分布式,需要使用zookeeper)
3. 12位的计数顺序号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号) 最高位是符号位,始终为0。






基于业务对Twitter生成全局唯一ID的SnowFlake算法的改造
文章图片


对twitter而言这样的ID生成方案满足:
1.每秒能够生成足够的ID数。 2.生成的ID按照时间大致有序。


4. 基于公司业务的分析
【基于业务对Twitter生成全局唯一ID的SnowFlake算法的改造】 经过大家的共同讨论,我们发现:
1.由于公司单个业务的ID生成量跟twitter比还差的太远,可以不需要用到那么多位自增码(甚至是时间位也有点多)。
2.同时考虑到业务量,我们不需要部署1024台机器那么多,所以可以减少机器码,还可以避免使用zookeeper(用更简单的检测方式代替)
3.既然打算做成公共服务,那么需要考虑接入多种业务后,产生的ID不冲突,需要增加业务码进行区分,同时为了保证服务能支持接入一定数量的业务,需要为业务码保留足够位数。

5.基于以上分析,我们对算法进行了改造:
基于业务对Twitter生成全局唯一ID的SnowFlake算法的改造
文章图片


主要变化在于减少7位机器码和2位自增码,用来扩充业务码!
这样的改造从理论上分析, 能够保证一台机器对一个业务每秒钟能产生100多万个唯一ID。


至于最终实际生成环境中产生的ID数目,以及这些ID是否会发生冲突,还需要后期的严格测试!


p.s. 本人在这段时间的实践中还发现算法里有两个点,需要强调下:
1.自增码在多线程环境中,需要加锁,避免同一毫秒内产生冲突。(后面还会分享一下,加锁对性能影响的测试分析)
2.多台机器上部署时,要保证机器的时间一致(需要用到NTP保证系统时间精确)
今天在这分享,希望大家多提宝贵意见,帮忙发现可以改进或者可能出现错误的地方

    推荐阅读