tinyservices-id 是一个高性能可扩展生成唯一id的服务。目前包含两种生成算法:雪花算法以及自增号段。 部署和使用都很便捷,无论是个人、团队、或是企业,都能够快速的使用 tinyservices-id 来生成唯一id。
tinyservices-id 有两种id生成算法:基于美团leaf的号段算法以及基于推特推出的雪花算法
分为三大模块:
id-server:server端,封装id生成算法以及对外提供http服务,可直接通过http获取id
id-sdk:sdk包,可直接依赖sdk获取id,省去了获取id的网络开销,性能极佳
id-portal:管理后台,通过管理后台新增/修改/删除的数据无需重启id-server服务,1分钟后可自动生效。每隔1分钟会自动同步数据到buffer中
雪花算法对中间件(MYSQL、ZOOKEEPER)弱依赖,每隔几秒会自动将中间件里的workerId刷到本地文件当中,这样即使中间件挂了的话也不影响id-server的正常使用,因为会自动降级到本地文件,因此也不会影响到业务系统
提供灵活配置以及可扩展能力,可自定义配置文件名称甚至无需配置文件,自定义实现类将配置放到配置中心。若雪花算法不希望用MYSQL或ZOOKEEPER,也可以自定义实现类进行实现,比如自定义ETCD等其他方式
版本要求:1.8+,在配置好后可以通过如下命令检查:
java -version
版本要求:5.6.5+,连接上MySQL后,可以通过如下命令检查:
SHOW VARIABLES WHERE Variable_name = 'version';
选择对应的发行版本下载代码,可以在如下链接进行下载:
scripts/sql/ts_id.sql
use ts_id;
show tables;
ts_id_segment
ts_id_token
ts_id_worker_id
根据不同环境修改不同的配置值(dev/test/pre/prod
),所修改文件的位置如下:
scripts/build.sh
scripts/build.sh
配置含义如下:
配置项 | 配置含义 | 是否必填 | 默认值 |
---|---|---|---|
id_server_config_db_driver | jdbc的driver | 必填 | 无 |
id_server_config_db_url | jdbc的url | 必填 | 无 |
id_server_config_db_username | mysql用户名 | 必填 | 无 |
id_server_config_db_password | mysql密码 | 必填 | 无 |
id_server_config_db_initial_size | 链接池初始化大小,不写则采取默认值 | 非必填 | 0 |
id_server_config_db_min_idle | 链接池最小空闲连接数,不写则采取默认值 | 非必填 | 0 |
id_server_config_db_max_active | 链接池最大活跃数,不写则采取默认值 | 非必填 | 8 |
id_server_config_db_max_wait | 链接池获取连接的最大等待时间,单位ms,不写则采取默认值 | 非必填 | -1 |
id_snowflake_mode | 雪花算法模式: LOCAL(本地文件的方式) MYSQL(对应 ts_id_worker_id 表)ZOOKEEPER(每次都根据 ip:port 创建一个顺序持久节点)RECYCLABLE_ZOOKEEPER(如果 ip:port 经常变的话那1023个workerId很容易就被耗光,此种方式是可循环利用workerId的ZOOKEEPER方式) |
非必填 | LOCAL |
id_snowflake_port | 雪花算法端口,不管采取何种方式,都会根据ip:port 生成唯一key与workerId一一对应。注:不会真正启动端口,只是作为唯一标识,所以和项目端口可重叠。 |
非必填 | 8080 |
id_snowflake_epoch | 雪花算法epoch,起始值,默认值:1648742400000L | 非必填 | 1648742400000L(2022-04-01 00:00:00) |
id_snowflake_zkConnectionAddr | 如果雪花算法采取ZOOKEEPER或RECYCLABLE_ZOOKEEPER模式,则需要配置ZOOKEEPER地址, | 非必填 | localhost:2181 |
id_server_log_dir | id-server项目日志目录 | 必填 | 无 |
id_portal_log_dir | id-portal项目日志目录 | 必填 | 无 |
id_server_port | id-server项目端口号 | 非必填 | 8080 |
id_portal_port | id-portal项目端口号 | 非必填 | 8080 |
scripts/build.sh
文件,比如:sh scripts/build.sh dev id-server
sh scripts/build.sh dev id-portal
可选参数:
$1:dev/test/pre/prod,分别代表开发环境/测试环境/预生产环境/生产环境。
$2:id-server/id-portal,分别代表id-server/id-portal两个moudle,也就是给哪个moudle打包,配置就是上面所输入dev/test/pre/prod所对应的变量。
编译打包完成后,可直接执行启动脚本,如下:
sh id-server/scripts/startup.sh
sh id-portal/scripts/startup.sh
验证id-server是否启动成功(也可以通过看日志的方式,日志位置就是id_server_log_dir
对应的值)
curl http(s)://ip:port/health/check
返回如下代表成功:
{
"code": 0,
"msg": "Processed successfully",
"data": 666
}
验证id-portal是否启动成功(也可以通过看日志的方式,日志位置就是id_portal_log_dir
对应的值)
直接浏览器打开http(s)://ip:port
,会出现如下页面:
id-portal
管理后台创建好token和业务类型的对应关系。id-portal
管理后台创建好Segment。使用上有两种使用方式,分别是Server和Sdk,Server的使用很简单,直接对外提供获取id的http接口。Sdk则需要业务系统依赖jar包然后调用方法获取id。下面详细介绍下二者使用方式和区别。
不管获取哪种算法的id,都需要添加如下header,否则会提示-4错误码,代表没权限:
tinyservice-id-token=token(token由id-portal管理后台Token菜单获取)
# 获取单个
GET http(s)://ip:port/segment/{业务类型}
# 批量获取
GET http(s)://ip:port/segment/{业务类型}/{获取的id数量}
# 获取单个
GET http(s)://ip:port/snowflake/{业务类型}
# 批量获取
GET http(s)://ip:port/snowflake/{业务类型}/{获取的id数量}
<dependency>
<groupId>com.gitee.tinyservices</groupId>
<artifactId>id-sdk</artifactId>
<version>1.0.0</version>
</dependency>
在classpath
(springboot
项目通常为resources
)下添加名为tinyservices_id_sdk.properties
的配置文件,包含如下配置项:
# id-server的地址,多个用英文逗号隔开,会随机选择一个地址使用
tinyservices.id.server=http://localhost:9990
# 要访问业务类型的token。可在id-portal管理后台配置/查看
tinyservices.id.token=U2FsdGVkX18uip/K7pLiM4ZD5RKrHacD64eKWCNfmW4=
// IdSdkTypeEnum.SEGMENT 号段模式
// IdSdkTypeEnum.SNOWFLAKE 雪花模式
AbstractIdSdk idSdk = IdSdkFactory.getInstance().getIdSdk(IdSdkTypeEnum.SEGMENT).registerConfigSupport();
// 获取id
for (int i = 0; i < 10; i ++) {
Long id = idSdk.getId("业务类型");
}
配置项 | 配置含义 | 是否必填 | 默认值 |
---|---|---|---|
tinyservices.id.token | token,可从id-portal管理后台配置/查看 | 必填 | 无 |
tinyservices.id.server | id-server服务列表,多个用逗号隔开,比如:http://localhost:9990 | 必填 | 无 |
tinyservices.id.readTimeout | sdk和server的超时时间(ms) | 非必填 | 5000ms |
tinyservices.id.connectTimeout | sdk和server的连接超时时间(ms) | 非必填 | 5000ms |
tinyservices.id.snowflake.epoch | 雪花算法的开始时间戳 | 非必填 | 1648742400000L(2022-04-01 00:00:00) |
Segment模式根据自身业务量规划好步长,比如业务QPS是10000,步长写了10,那可能瞬时流量进来的话会获取到少部分id为null的情况,因为步长太小,双buffer都被瞬时流量打满。
如果对性能有极高要求的话,推荐Sdk方式,此方式直接依赖jar包调用本地方法的方式生成id,由于Sdk的方式免去了网络开销,理论上QPS可达千万。
如果对性能要求不高的话可以使用Server方式,直接请求http接口,减少系统依赖。
给项目添加对应环境变量即可,IDEA添加环境变量的方式如下:
添加如下环境变量:
spring.datasource.driver=com.mysql.cj.jdbc.Driver;spring.datasource.url=jdbc:mysql://localhost:3306/ts_id?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT;spring.datasource.username=root;spring.datasource.password=12345678;spring.datasource.initial-size=;spring.datasource.min-idle=;spring.datasource.max-active=;spring.datasource.max-wait=;id_server_log_dir=/data/logs/id-server;server_port=9990;id_server_snowflake_mode=MYSQL;id_server_snowflake_port=8888;id_server_snowflake_epoch=1648742400000;id_server_snowflake_zkConnectionAddr=localhost:2181
数据库连接、用户名、密码、端口等等参数都根据自身环境自行修改即可。
添加如下环境变量:
spring.datasource.driver=com.mysql.cj.jdbc.Driver;spring.datasource.url=jdbc:mysql://localhost:3306/ts_id?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT;spring.datasource.username=root;spring.datasource.password=12345678;spring.datasource.initial-size=;spring.datasource.min-idle=;spring.datasource.max-active=;spring.datasource.max-wait=;id_portal_log_dir=/data/logs/id-portal;server_port=9990
数据库连接、用户名、密码、端口等等参数都根据自身环境自行修改即可。
不管是Segment还是Token方式,新增或修改配置后都是一分钟生效,也就是一分钟后id-server服务可用这份配置。
目前内置四种模式:LOCAL本地文件模式、MYSQL模式、ZOOKEEPER模式以及RECYCLABLE_ZOOKEEPER可回收利用workerId的ZOOKEEPER模式,若想采用其他中间件作为注册中心,那么如下步骤:
首先自定义一个Class
继承AbstractIdSnowflakeHolder
类且重写相应的方法,可参考其他子类,比如:ZookeeperIdSnowflakeHolder
其次在枚举类IdSnowflakeHolderTypeEnum
当中新增相应类型(此类型必须和配置文件里的tinyservices.id.snowflake.mode
配置一一对应)
最后修改工厂类的方法IdSnowflakeHolderFactory#getIdSnowflakeHolder
,为其新增case
分支,值为新增的枚举类型
RECYCLABLE_ZOOKEEPER模式首次启动慢正常的,此模式会在启动的时候提前在Zookeeper创建1023个持久节点作为workerId池,利于workerId的复用。因为是持久节点,所以只有首次创建会很慢,之后启动会发现已存在1023个持久节点则不再重复创建。
如项目启动过程中出现MySQL驱动错误的话,则自行按需修改版本号,目前内置版本是8.0.21,在根pom.xml
文件中。如下:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
<scope>runtime</scope>
</dependency>
修改后再打包的时候别忘了修改
scripts/build.sh
里的id_server_config_db_driver
配置。若是本地部署代码运行的话则别忘了修改环境变量里的
id_server_config_db_driver
配置。
如果不想采取默认的配置文件名称tinyservices_id_sdk.properties
,那可以采取如下方式进行自定义:
AbstractIdSdk idSdk = IdSdkFactory.getInstance().getIdSdk(IdSdkTypeEnum.SNOWFLAKE, "自定义配置文件名称.properties").registerConfigSupport();
// 获取id
for (int i = 0; i < 10; i ++) {
Long id = idSdk.getId("业务类型");
}
如果不想采取配置文件的方式,公司规范都放到配置中心该怎么办?可以采取如下方式进行自定义:
/**
* 可选择性重写如下五个方法:
* String getBizToken();
* String getServerUrl();
* int getReadTimeout();
* int getConnectTimeout();
* long getEpoch();
*/
public class CustomIdConfigSupport extends AbstractIdConfigSupport {
@Override
public String getServerUrl() {
// 可通过配置中心获取
return null;
}
@Override
public String getBizToken() {
// 可通过配置中心获取
return null;
}
// ... 省略其他非必需重写的方法
}
AbstractIdSdk idSdk = IdSdkFactory.getInstance().getIdSdk(IdSdkTypeEnum.SNOWFLAKE).registerConfigSupport(new CustomIdConfigSupport());
// 获取id
for (int i = 0; i < 10; i ++) {
Long id = idSdk.getId("业务类型");
}
背景:sdk方式一个配置文件只允许配置一个token,若一个项目想获取不同业务类型的token该如何获取呢?
解答:有两种方式可以解决:
一个业务类型支持配置多个token,可以将不同业务类型都配置一个公共的token,后台目前只允许生成token,不允许自定义token,如需这么做可以二开下id-portal
,放开token禁止输入的限制,也可以手动修改ts_id_worker_id
表数据。
或者采取自定义配置文件的方式,比如要获取两个业务类型的id:
第一个业务类型:
AbstractIdSdk idSdk = IdSdkFactory.getInstance().getIdSdk(IdSdkTypeEnum.SEGMENT, "sdk_1.properties").registerConfigSupport();
idSdk.getId("test1");
第二个业务类型:
AbstractIdSdk idSdk = IdSdkFactory.getInstance().getIdSdk(IdSdkTypeEnum.SEGMENT, "sdk_2.properties").registerConfigSupport();
idSdk.getId("test2");
若贵司接入了tinyservices-id
,欢迎私信/评论贵司名称,您的支持是我永恒的动力。
如有任何问题请提issue。https://gitee.com/tinyservices/tinyservices-id/issues
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
1. 开源生态
2. 协作、人、软件
3. 评估模型