发号器:雪花算法(Snowflake)
雪花算法(Snowflake)是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器。第一个bit位(1bit):Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。时间戳部分(41bit):毫秒级的时间,不建议存当前时间戳,而是用(当前时间戳 - 固定开始时间戳)的差值
雪花算法(Snowflake)是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器。
第一个bit位(1bit):Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。
时间戳部分(41bit):毫秒级的时间,不建议存当前时间戳,而是用(当前时间戳 - 固定开始时间戳)的差值,可以使产生的ID从更小的值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年
工作机器id(10bit):也被叫做workId,这个可以灵活配置,机房或者机器号组合都可以。
序列号部分(12bit):自增值支持同一毫秒内同一个节点可以生成4096个ID, 2^12=4096
Snowflake 算法有几个比较大的问题:
- 低并发场景会产生连续偶数,原因是低并发场景系统时钟总是走到下一个毫秒值,导致序列号重置为 0 。
- 依赖系统时钟,时钟回拨会拒绝生成新的 ID (直接抛出异常)。(美团的leaf, 用如果时间差在5ms内,则等待 时间差<<1, 然后再判断)
- Woker ID 和 Data Center ID 的管理比较麻烦,特别是同一个服务的不同集群节点需要保证每个节点的 Woker ID 和 Data Center ID 组合唯一。
Leaf-snowflake
Leaf-snowflake
不同于原始snowflake地方,主要是在workId的生成上,Leaf-snowflake
依靠Zookeeper
生成workId
,也就是上边的机器ID
(占5比特)+ 机房ID
(占5比特)。Leaf
中workId是基于ZooKeeper的顺序Id
来生成的,每个应用在使用Leaf-snowflake时,启动时都会都在Zookeeper中生成一个顺序Id,相当于一台机器对应一个顺序节点,也就是一个workId。
Leaf-snowflake
启动服务的过程大致如下:
- 启动Leaf-snowflake服务,连接Zookeeper,在leaf_forever父节点下检查自己是否已经注册过(是否有该顺序子节点)。
- 如果有注册过直接取回自己的workerID(zk顺序节点生成的int类型ID号),启动服务。
- 如果没有注册过,就在该父节点下面创建一个持久顺序节点,创建成功后取回顺序号当做自己的workerID号,启动服务。
但Leaf-snowflake
对Zookeeper是一种弱依赖关系,除了每次会去ZK拿数据以外,也会在本机文件系统上缓存一个workerID
文件。一旦ZooKeeper出现问题,恰好机器出现故障需重启时,依然能够保证服务正常启动。
启动Leaf-snowflake
模式也比较简单,起动本地ZooKeeper,修改一下项目中的leaf.properties
文件,关闭leaf.segment模式
,启用leaf.snowflake
模式即可。
leaf.segment.enable=false
leaf.snowflake.enable=true
leaf.snowflake.zk.address=127.0.0.1
leaf.snowflake.port=2181
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)