冰河开源了全网首个完全开源的分布式全局有序序列号(分布式ID)框架!!

1. 序列号

最大峰值型

20位,理论上每秒内平均可产生2^20= 1048576个ID,百万级别,如果系统的网络IO和CPU足够强大,可承受的峰值达到每毫秒百万级别。

最小粒度型

10位,每毫秒内序列号总计2^10=1024个, 也就是每个毫秒最多产生1000+个ID,理论上承受的峰值完全不如我们最大峰值方案。

2. 秒级时间/毫秒级时间

最大峰值型

30位,表示秒级时间,2^30/60/60/24/365=34,也就是可使用30+年。

最小粒度型

40位,表示毫秒级时间,2^40/1000/60/60/24/365=34,同样可以使用30+年。

3. 机器ID

10位, 2^10=1024, 也就是最多支持1000+个服务器。中心发布模式和REST发布模式一般不会有太多数量的机器,按照设计每台机器TPS 1万/s,10台服务器就可以有10万/s的TPS,基本可以满足大部分的业务需求。

但是考虑到我们在业务服务可以使用内嵌发布方式,对机器ID的需求量变得更大,这里最多支持1024个服务器。

4. 生成方式

2位,用来区分三种发布模式:嵌入发布模式,RPC发布模式,REST发布模式。

00:嵌入发布模式

01:RPC发布模式

02:REST发布模式

03:保留未用

5. 序列号类型

1位,用来区分两种ID类型:最大峰值型和最小粒度型。

0:最大峰值型

1:最小粒度型

6. 版本

1位,用来做扩展位或者扩容时候的临时方案。

0:默认值,以免转化为整型再转化回字符串被截断

1:表示扩展或者扩容中

作为30年后扩展使用,或者在30年后ID将近用光之时,扩展为秒级时间或者毫秒级时间来挣得系统的移植时间窗口,其实只要扩展一位,完全可以再使用30年。

并发处理

对于中心服务器和REST发布方式,ID生成的过程涉及到网络IO和CPU操作,ID的生成基本都是内存到高速缓存的操作,没有IO操作,网络IO是系统的瓶颈。

相对于CPU计算速度来说网络IO是瓶颈,因此,ID产生的服务使用多线程的方式,对于ID生成过程中的竞争点time和sequence,这里使用了多种实现方式

  1. 使用concurrent包的ReentrantLock进行互斥,这是缺省的实现方式,也是追求性能和稳定两个目标的妥协方案。
  1. 使用传统的synchronized进行互斥,这种方式的性能稍微逊色一些,通过传入JVM参数-Dmykit.serial.sync.lock.impl.key=true来开启。
  1. 使用CAS方式进行互斥,这种实现方式的性能非常高,但是在高并发环境下CPU负载会很高,通过传入JVM参数-Dmykit.serial.atomic.impl.key=true来开启。

机器ID的分配

我们将机器ID分为两个区段,一个区段服务于RPC发布模式和REST发布模式,另外一个区段服务于嵌入发布模式。

0-923:嵌入发布模式,预先配置,(或者由Zookeeper产生),最多支持924台内嵌服务器

924 – 1023:中心服务器发布模式和REST发布模式,最多支持300台,最大支持300*1万=300万/s的TPS

如果嵌入式发布模式和RPC发布模式以及REST发布模式的使用量不符合这个比例,我们可以动态调整两个区间的值来适应。

另外,各个垂直业务之间具有天生的隔离性,每个业务都可以使用最多1024台服务器。

与Zookeeper集成

对于嵌入发布模式,服务启动需要连接Zookeeper集群,Zookeeper分配一个0-923区间的一个ID,如果0-923区间的ID被用光,Zookeeper会分配一个大于923的ID,这种情况,拒绝启动服务。

如果不想使用Zookeeper产生的唯一的机器ID,我们提供缺省的预配的机器ID解决方案,每个使用统一分布式全局序列号(分布式ID)服务的服务需要预先配置一个默认的机器ID。

时间同步

使用mykit-serial生成分布式全局序列号(分布式ID)时,需要我们保证服务器的时间正常。此时,我们可以使用Linux的定时任务crontab,定时通过授时服务器虚拟集群(全球有3000多台服务器)来核准服务器的时间。

ntpdate -u pool.ntp.orgpool.ntp.org

性能


最终的性能验证要保证每台服务器的TPS达到1万/s以上。

Restful API文档


产生分布式全局序列号

  • 描述:根据系统时间产生一个全局唯一的全局序列号并且在方法体内返回。

  • 路径:/genSerialNumber

  • 参数:N/A

  • 非空参数:N/A

  • 示例:http://localhost:8080/genSerialNumber

  • 结果:3456526092514361344

反解全局序列号

  • 描述:对产生的serialNumber进行反解,在响应体内返回反解的JSON字符串。

  • 路径:/expSerialNumber

  • 参数:serialNumber=?

  • 非空参数:serialNumber

  • 示例:http://localhost:8080/expSerialNumber?serialNumber=3456526092514361344

  • 结果:{“genMethod”:2,“machine”:1022,“seq”:0,“time”:12758739,“type”:0,“version”:0}

翻译时间

  • 描述:把长整型的时间转化成可读的格式。

  • 路径:/transtime

  • 参数:time=?

  • 非空参数:time

  • 示例:http://localhost:8080/transtime?time=12758739

  • 结果:Thu May 28 16:05:39 CST 2015

制造全局序列号

  • 描述:通过给定的分布式全局序列号元素制造分布式全局序列号。

  • 路径:/makeSerialNumber

  • 参数:genMethod=?&machine=?&seq=?&time=?&type=?&version=?

  • 非空参数:time,seq

  • 示例:http://localhost:8080/makeSerialNumber?genMethod=2&machine=1022&seq=0&time=12758739&type=0&version=0

  • 结果:3456526092514361344

Java API文档


产生全局序列号

  • 描述:根据系统时间产生一个全局唯一的分布式序列号(分布式ID)并且在方法体内返回。

  • 类:SerialNumberService

  • 方法:genSerialNumber

  • 参数:N/A

  • 返回类型:long

  • 示例:long serialNumber= serialNumberService.genSerialNumber();

反解全局序列号

  • 描述:对产生的分布式序列号(分布式ID)进行反解,在响应体内返回反解的JSON字符串。

  • 类:SerialNumberService

  • 方法:expSerialNumber

  • 参数:long serialNumber

  • 返回类型:SerialNumber

  • 示例:SerialNumber serialNumber = serialNumberService.expSerialNumber(3456526092514361344);

翻译时间

  • 描述:把长整型的时间转化成可读的格式。

  • 类:SerialNumberService

  • 方法:transTime

  • 参数:long time

  • 返回类型:Date

  • 示例:Date date = serialNumberService.transTime(12758739);

制造全局序列号(1)

  • 描述:通过给定的分布式序列号元素制造分布式序列号。

  • 类:SerialNumberService

  • 方法:makeSerialNumber

  • 参数:long time, long seq

  • 返回类型:long

  • 示例:long serialNumber= SerialNumberService.makeSerialNumber(12758739, 0);

制造全局序列号(2)

  • 描述:通过给定的ID元素制造ID。

  • 类:SerialNumberService

  • 方法:makeSerialNumber

  • 参数:long machine, long time, long seq

  • 返回类型:long

  • 示例:long serialNumber= serialNumberService.makeSerialNumber(1, 12758739, 0);

制造全局序列号(3)

  • 描述:通过给定的分布式序列号元素制造ID。

  • 类:SerialNumberService

  • 方法:makeSerialNumber

  • 参数:long genMethod, long machine, long time, long seq

  • 返回类型:long

  • 示例:long serialNumber= serialNumberService.makeSerialNumber(0, 1, 12758739, 0);

制造全局序列号(4)

  • 描述:通过给定的分布式序列号元素制造ID。

  • 类:SerialNumberService

  • 方法:makeSerialNumber

  • 参数:long type, long genMethod, long machine, long time, long seq

  • 返回类型:long

  • 示例:long serialNumber= serialNumberService.makeSerialNumber(0, 2, 1, 12758739, 0);

制造全局序列号(5)

  • 描述:通过给定的ID元素制造ID。

  • 类:SerialNumberService

  • 方法:makeSerialNumber

  • 参数:long version, long type, long genMethod, long machine, long time, long seq

  • 返回类型:long

  • 示例:long serialNumber = serialNumberService.makeSerialNumber(0, 0, 2, 1, 12758739, 0);

FAQ


自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

image.png

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
%以上Java开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后

[外链图片转存中…(img-v18orKyo-1712766143823)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值