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

本文介绍了冰河开源的分布式全局有序序列号框架,包括发布模式、序列号类型、数据结构、并发处理和机器ID分配等关键内容。框架支持嵌入、RPC和REST发布模式,提供了最大峰值型和最小粒度型两种序列号类型,以适应不同的性能需求。同时,详细阐述了并发处理策略和机器ID的动态分配,以及与Zookeeper的集成,确保服务的高效和稳定性。
摘要由CSDN通过智能技术生成
  • mykit-bean:提供统一的bean类封装和整个框架使用的常量等信息。

  • mykit-common:封装整个框架通用的工具类。

  • mykit-config:提供全局配置能力。

  • mykit-core:整个框架的核心实现模块。

  • mykit-db:存放数据库脚本。

  • mykit-interface:整个框架的核心抽象接口。

  • mykit-service:基于Spring实现的核心功能。

  • mykit-rpc:以RPC方式对外提供服服务(后续支持Dubbo,motan、sofa、SpringCloud、SpringCloud Alibaba等主流的RPC框架)。

  • mykit-server:目前实现了Dubbo方式,后续迁移到mykit-rpc模块。

  • mykit-rest:基于SpringBoot实现的Rest服务。

  • mykit-rest_netty:基于Netty实现的Rest服务。

  • mykit-test:整个框架的测试模块,通过此模块可以快速掌握mykit-serial的使用方式。

发布模式

根据最终的客户使用方式,可分为嵌入发布模式,RPC发布模式和Rest发布模式。

  1. 嵌入发布模式:只适用于Java客户端,提供一个本地的Jar包,Jar包是嵌入式的原生服务,需要提前配置本地机器ID(或者服务启动时,由Zookeeper动态分配唯一的分布式序列号),但是不依赖于中心服务器。

  2. RPC发布模式:只适用于Java客户端,提供一个服务的客户端Jar包,Java程序像调用本地API一样来调用,但是依赖于中心的分布式序列号(分布式ID)产生服务器。

  3. REST发布模式:中心服务器通过Restful API提供服务,供非Java语言客户端使用。

发布模式最后会记录在生成的全局序列号中。

序列号类型

根据时间的位数和序列号的位数,可分为最大峰值型和最小粒度型。

1. 最大峰值型:采用秒级有序,秒级时间占用30位,序列号占用20位

| 字段 | 版本 | 类型 | 生成方式 | 秒级时间 | 序列号 | 机器ID |

| :-: | :-: | :-: | :-: | :-: | :-: | :-: |

| 位数 | 63 | 62 | 60-61 | 30-59 | 10-29 | 0-9 |

2. 最小粒度型:采用毫秒级有序,毫秒级时间占用40位,序列号占用10位

| 字段 | 版本 | 类型 | 生成方式 | 毫秒级时间 | 序列号 | 机器ID |

| :-: | :-: | :-: | :-: | :-: | :-: | :-: |

| 位数 | 63 | 62 | 60-61 | 20-59 | 10-19 | 0-9 |

最大峰值型能够承受更大的峰值压力,但是粗略有序的粒度有点大,最小粒度型有较细致的粒度,但是每个毫秒能承受的理论峰值有限,为1024,同一个毫秒如果有更多的请求产生,必须等到下一个毫秒再响应。

分布式序列号(分布式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,基本可以满足大部分的业务需求。

但是考虑到我们在业务服务可以使用内嵌发布方式࿰

public synchronized String nextId() { long timestamp = timeGen(); //获取当前毫秒数 //如果服务器时间有问题(时钟后退) 报错。 if (timestamp < lastTimestamp) { throw new RuntimeException(String.format( "Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } //如果上次生成时间和当前时间相同,在同一毫秒内 if (lastTimestamp == timestamp) { //sequence自增,因为sequence只有12bit,所以和sequenceMask相与一下,去掉高位 sequence = (sequence + 1) & sequenceMask; //判断是否溢出,也就是每毫秒内超过4095,当为4096时,与sequenceMask相与,sequence就等于0 if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); //自旋等待到下一毫秒 } } else { sequence = 0L; //如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加 } lastTimestamp = timestamp; long suffix = (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; String datePrefix = DateFormatUtils.format(timestamp, "yyyyMMddHHMMssSSS"); return datePrefix + suffix; } protected long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } protected long timeGen() { return System.currentTimeMillis(); } private byte getLastIP(){ byte lastip = 0; try{ InetAddress ip = InetAddress.getLocalHost(); byte[] ipByte = ip.getAddress(); lastip = ipByte[ipByte.length - 1]; } catch (UnknownHostException e) { e.printStackTrace(); } return lastip; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值