asong要出新系列之雪花算法(go)
Leaf——美团点评分布式ID生成系统
① 毫秒数在高位,自增序列在低位,整个ID都是趋势递增的(但并不是全局有序,单机单实例是有序的)。
② 不依赖数据库等第三方系统,部署灵活,生成id的效率高。
③ 能根据自身业务,自己分配bit位。
强依赖机器时钟,如果机器上时钟回拨,会导致发号重复。
snowFlake ID结构就是一个64bit的int型数据。
固定为0,因为在计算机存储中,最高位表示符号,因为我们需要正数的id,所以第一个位恒为0;
时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
41bit可以表示的数值范围是0 - (2^41 -1),所以一共可以表示的年限是 (2^41 -1)/(1000 * 60 * 60 * 24 * 365)= 69 年。
我们可以设置一个初始时间戳,每次获取实际时间戳之后,减去设定的初始时间戳,来作为自己系统的时间戳。
这样从我们的系统起始,能用69年。
表示工作的机器id。
如果我们的系统是分布式的,这样每一台机器生成的分布式id也不能重复。
2^10=1024表示当前规则允许分布式最大节点数为1024个节点。
当然,如果节点没有这么多的话,可以将这10个bit按自己的定义划分,比如节点id、业务id等。
用来记录相同毫秒时间内产生的不同id,12bit可以表示2^12-1=4095,也就是说同一台机器在同一毫秒内,有4095个可以用的id。
① 时间差比较大的话,直接抛出异常,人工处理。【备用服务节点的方法。如果某一节点时钟回拨很大,直接下线该节点,采用备用节点替补的方式。这样的话,涉及到机器id的自动发放与回收的问题,美团采用的方法是使用Zookeeper持久顺序节点的特性自动对snowflake节点配置wokerId】
② 如果时钟回拨,时间差很小的范围,几ms的,将线程阻塞几ms,再次获取时间戳,看看是否比上一次大了。
③ 不以系统的时间戳作为标准。首先,记录系统启动时候的时间戳,每ms会有2^12-1=4095个id,系统业务按照序列号依次进行获取,当4095个id获取完毕后,时间戳自动加一。也就是说,时间戳不在获取系统的,而是由自己的业务去控制,当该毫秒级的时间戳的4095个id用完之后,让时间戳自增一,继续依次获取。