分佈式ID生成方案(五):SpringBoot2.X集成滴滴Tinyid

簡介

Tinyid是用Java開發的一款分佈式id生成系統,基於數據庫號段算法實現,簡單來說是數據庫中保存了可用的id號段,tinyid會將可用號段加載到內存中,之後生成id會直接內存中產生。

特性

  • 全局唯一的long型id
  • 趨勢遞增的id,即不保證下一個id一定比上一個大
  • 非連續性
  • 提供http和java client方式接入
  • 支持批量獲取id,支持生成1,3,5,7,9…序列的id
  • 支持多個db的配置,無單點

可用性

  • 依賴db,當db不可用時,因爲server有緩存,所以還可以使用一段時間,如果配置了多個db,則只要有1個db存活,則服務可用
  • 使用tiny-client,只要server有一臺存活,則理論上可用,server全掛,因爲client有緩存,也可以繼續使用一段時間

適用場景:

只關心id是數字,趨勢遞增的系統,可以容忍id不連續,有浪費的場景

不適用場景:

類似訂單id的業務(因爲生成的id大部分是連續的,容易被掃庫、或者測算出訂單量)

接入實現

  • Http方式

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的能力,網絡傳輸速度

  • Java Client方式

新建數據表及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依賴

<dependency>
    <groupId>com.xiaoju.uemc.tinyid</groupId>
    <artifactId>tinyid-client</artifactId>
    <version>0.1.0-SNAPSHOT</version>
</dependency>

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<Long> tinyBatchId(){
    List<Long> ids = TinyId.nextId("test", 10);
    return ids;
}

該方式,id爲本地生成,號段長度(step)越長,qps越大,如果將號段設置足夠大,則qps可達1000w+,推薦使用方式。

完整代碼地址:SpringBoot項目集成Tinyid生成全局性ID

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章