Tinyid是用Java开发的一款分布式id生成系统,基于数据库号段算法实现,简单来说是数据库中保存了可用的id号段,tinyid会将可用号段加载到内存中,之后生成id会直接内存中产生。
只关心id是数字,趋势递增的系统,可以容忍id不连续,有浪费的场景
类似订单id的业务(因为生成的id大部分是连续的,容易被扫库、或者测算出订单量)
1. 导入源码
git clone https://github.com/didi/tinyid.git
2. 新建数据表
CREATE TABLE `tiny_id_info` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '业务类型,唯一',
`begin_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '开始id,仅记录初始值,无其他含义。初始化时begin_id和max_id应相同',
`max_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '当前最大id',
`step` int(11) DEFAULT '0' COMMENT '步长',
`delta` int(11) NOT NULL DEFAULT '1' COMMENT '每次id增量',
`remainder` int(11) NOT NULL DEFAULT '0' COMMENT '余数',
`create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间',
`version` bigint(20) NOT NULL DEFAULT '0' COMMENT '版本号',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_biz_type` (`biz_type`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'id信息表';
CREATE TABLE `tiny_id_token` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`token` varchar(255) NOT NULL DEFAULT '' COMMENT 'token',
`biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '此token可访问的业务类型标识',
`remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
`create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'token信息表';
INSERT INTO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`)
VALUES
(1, 'test', 1, 1, 100000, 1, 0, '2018-07-21 23:52:58', '2018-07-22 23:19:27', 1);
INSERT INTO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`)
VALUES
(2, 'test_odd', 1, 1, 100000, 2, 1, '2018-07-21 23:52:58', '2018-07-23 00:39:24', 3);
INSERT INTO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`)
VALUES
(1, '0f673adf80504e2eaa552f5d791b644c', 'test', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');
INSERT INTO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`)
VALUES
(2, '0f673adf80504e2eaa552f5d791b644c', 'test_odd', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');
3. 修改Server数据库配置
server.port=9999
server.context-path=/tinyid
batch.size.max=100000
datasource.tinyid.names=primary
datasource.tinyid.type=org.apache.tomcat.jdbc.pool.DataSource
datasource.tinyid.primary.driver-class-name=com.mysql.jdbc.Driver
datasource.tinyid.primary.url=jdbc:mysql://localhost:3306/demo?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
datasource.tinyid.primary.username=root
datasource.tinyid.primary.password=123456
4. 启动Server测试
nextId:
curl 'http://localhost:9999/tinyid/id/nextId?bizType=test&token=0f673adf80504e2eaa552f5d791b644c'
response:{"data":[2],"code":200,"message":""}
nextId Simple:
curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c'
response: 3
with batchSize:
curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c&batchSize=10'
response: 4,5,6,7,8,9,10,11,12,13
Get nextId like 1,3,5,7,9...
bizType=test_odd : delta is 2 and remainder is 1
curl 'http://localhost:9999/tinyid/id/nextIdSimple?bizType=test_odd&batchSize=10&token=0f673adf80504e2eaa552f5d791b644c'
response: 3,5,7,9,11,13,15,17,19,21
使用该方式性能取决于http server的能力,网络传输速度
新建数据表及Server数据库配置,如HTTP方式的2、3两步。
下面就将该方式集成在基于Mysql数据库生成批量ID项目中使用:
1. 将源码进行打包,在本地仓库中生成jar包
直接在maven中install tinyid即可,刚开始自己从子模块入手,base生成jar之后,继续生成client、server,结果一直出错:
原因是如果你有子项目引用了父项目的POM,但没有在父项目POM目录下执行安装操作,这个问题就会出现。针对子模块依赖兄弟子模块的情况,需要在父项目POM目录下至少执行一次安装。
解决办法是直接在父项目下进行install即可。
另外需要注意的是在install的过程中,要保持server端服务可用,不然client会失败,连不上server错误。
2. 项目中引入tinyid-client maven依赖
com.xiaoju.uemc.tinyid
tinyid-client
0.1.0-SNAPSHOT
3. 项目中增加tinyid_client配置文件
#配置server端及token
tinyid.server=localhost:9999
tinyid.token=0f673adf80504e2eaa552f5d791b644c
4. 项目中提供两个controller接口,便于查看结果
/**
* 集成tinyid生成单个id
* @return
*/
@GetMapping("/tinyid/simple")
public Long tinyid(){
Long id = TinyId.nextId("test");
return id;
}
/**
* 集成tinyid生成批量id
* @return
*/
@GetMapping("/tinyid/batch")
public List tinyBatchId(){
List ids = TinyId.nextId("test", 10);
return ids;
}
该方式,id为本地生成,号段长度(step)越长,qps越大,如果将号段设置足够大,则qps可达1000w+,推荐使用方式。
完整代码地址:SpringBoot项目集成Tinyid生成全局性ID