针对每个公司,随着服务化演进,单个服务越来越多,数据库分的越来越细,有的时候一个业务需要分成好几个库,这时候自增主键或者序列之类的主键id生成方式已经不再满足需求,分布式系统中需要的是一个全局唯一的id生成规则。既然号称在全局分布式系统中唯一,那么主键的生成规则必然要复杂一些,以前看过很多资料,都对雪花的生成一知半解,最后才发现是对Java的位运算没有彻底了解,这里想针对雪花算法,以一种浅显的的方式来进行学习,去除以前的一知半解和对雪花算法的神秘感。
雪花算法生成的最终结果其实就是一个long类型的Java长整型数字,这是一个大前提!算法所有的内容都是针对这个数字进行运算的。Java基础类型相信都很熟悉,有32位的整型int类型,和64位的长整型long类型。我们单说long类型,64位说的是数字转换为二进制形式时候的表现,其中第一位表示的是正负,也就是符号,剩下的63位表示的是字面数字。我们来简单看一下几个关键的long数字转换成二进制的形式:
![3277f435be2140ba5a793b0a9e4859c6.png](https://i-blog.csdnimg.cn/blog_migrate/e4ae2796a2e9f9ea4f65640500ac8ee9.png)
再来看一个二进制数字转换为long类型:
![3d45775737ff663833f05279d71675ad.png](https://i-blog.csdnimg.cn/blog_migrate/968524f4f90dc14913ca4678e86648db.jpeg)
上面都是Java基础知识,相信大家都懂。
生成一个long类型的数字id,其实就是对这64位的二进制形式里面填值,把这64位分成几个部分,彼此间互不影响,每部分都有自己的生成规则,这样在一定的简单的大前提下,能保证全局唯一。
先说第一位,long类型的数字是有符号的,第一位是0就是正数,1是负数,我们生成的id必然要正数,所以第一位可以确定为0不变。
剩下的63位分成三大部分,第一部分占41位,用来表示时间,什么时间后面会详细介绍。第二部分占10位,用来表示程序所在机器的信息,剩下的第三部分占12位,填充的是一个序列,可以理解为递增数字,这样前面的时间和机器数字如果都一样的话,用序列的区别来生成不同的id。
![3a63d12f849f10a14c897db59c00eb9b.png](https://i-blog.csdnimg.cn/blog_migrate/7d6e4da1938cd63d9c474efa5f243a94.jpeg)
上面的三大块信息转换成数字,填充到63位当中,基本可以保证任何时间任何机器生产的任何id不重复,可以推理出,时间和序列都是不可控的,但是机器信息是我们可以控制的,也就是说设置好机器信息是分布式id不重复的关键。
根据上面的理论可以开始学习雪花算法。
代码地址:https://gitee.com/blueses/snowflake-demo 01