分散IDジェネレータについて知らない人は、前回の「分散ID生成方法9選」を復習してください。 Tinyid は Didi が開発した分散 ID システムです。 Meituan(Leaf)のリーフセグメントアルゴリズムに基づいたアップグレードです。データベースのマルチマスターノードモードをサポートするだけでなく、tinyid-client クライアントアクセスも提供しており、より便利に使用できます。しかし、Meituan (Leaf) とは異なり、Tinyid は数字セグメント モードのみをサポートし、スノーフレーク モードはサポートしていません。 Tinyidの特徴 - グローバルに一意な長いID
- トレンド増加ID
- httpおよびJavaクライアントアクセスを提供する
- IDの一括取得をサポート
- 1、3、5、7、9 の順序で ID を生成することをサポートします...
- 複数のDB構成をサポート
適用可能なシナリオ: IDが数字であることと増加傾向であることのみを考慮し、不連続なIDを許容し、IDの無駄を許容できるシステム 適用されないシナリオ: 注文IDのようなビジネスの場合、生成されるIDのほとんどは連続しているため、簡単にスキャンされたり、注文数量やその他の情報が推測されたりする可能性があります。 Tinyid の原理 Tinyid はセグメント モードに基づいて実装されます。セグメント モードの原理を簡単に説明します。これは、データベースから自動増分 ID を一括で取得し、そのたびにデータベースからセグメント範囲を取り出すというものです。たとえば、(1,1000] は 1000 個の ID を表します。ビジネス サービスは、1 から 1000 までの自動増分 ID をローカルで生成し、メモリにロードします。 Tinyid は利用可能な数値セグメントをメモリに読み込み、メモリ内に ID を生成します。使用可能な番号セグメントは、ID が最初に取得されたときに読み込まれます。現在の番号セグメントがある程度使用されると、システムは次の利用可能な番号セグメントを非同期的にロードし、メモリ内に常に利用可能な番号セグメントが存在するようにして、番号発行サービスが停止した後も一定期間利用可能な ID が存在するようにします。 概略図はおおよそ次のようになります。 Tinyid 概略図 Tinyid 実装 Tinyid の GitHub アドレス: https://github.com/didi/tinyid.git Tinyid は 2 つの呼び出しメソッドを提供します。1 つは Tinyid-server によって提供される http メソッドに基づいており、もう 1 つは Tinyid-client クライアント メソッドです。どちらの方法を使用して呼び出す場合でも、Tinyid を構築するには、事前に tiny_id_info および tiny_id_token テーブルを作成する必要があります。 - テーブル `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) デフォルト '0' コメント 'ステップ長',
- `delta` int(11) NOT NULL DEFAULT '1' COMMENT '各IDの増分',
- `remainder` int(11) NOT NULL デフォルト '0' コメント 'remainder',
- `create_time` タイムスタンプ NOT NULL デフォルト '2010-01-01 00:00:00' コメント '作成時間',
- `update_time` タイムスタンプ NOT NULL デフォルト '2010-01-01 00:00:00' コメント '更新時間',
- `version` bigint(20) NOT NULL DEFAULT '0' COMMENT 'バージョン番号',
- 主キー (`id`)、
- ユニークキー `uniq_biz_type` (`biz_type`)
- )エンジン= InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 COMMENT 'id information 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 'このトークンがアクセスできるビジネスタイプ識別子',
- `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '備考',
- `create_time` タイムスタンプ NOT NULL デフォルト '2010-01-01 00:00:00' コメント '作成時間',
- `update_time` タイムスタンプ NOT NULL デフォルト '2010-01-01 00:00:00' コメント '更新時間',
- 主キー (`id`)
- )エンジン= InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 COMMENT 'トークン情報テーブル';
- `tiny_id_info` に INSERT INTO (`id`、`biz_type`、`begin_id`、`max_id`、`step`、`delta`、`remainder`、`create_time`、`update_time`、`version`)
- 価値観
- (1, 'テスト', 1, 1, 100000, 1, 0, '2018-07-21 23:52:58', '2018-07-22 23:19:27', 1);
- `tiny_id_info` に INSERT INTO (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`)
- 価値観
- (2, 'test_odd', 1, 1, 100000, 2, 1, '2018-07-21 23:52:58', '2018-07-23 00:39:24', 3);
- `tiny_id_token` に INSERT します (`id`、`token`、`biz_type`、`remark`、`create_time`、`update_time`)
- 価値観
- (1, '0f673adf80504e2eaa552f5d791b644c', 'テスト', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');
- `tiny_id_token` に INSERT します (`id`、`token`、`biz_type`、`remark`、`create_time`、`update_time`)
- 価値観
- (2, '0f673adf80504e2eaa552f5d791b644c', 'test_odd', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');
tiny_id_infoテーブルは、特定のビジネスパーティ番号セグメント情報のデータテーブルです。 max_id: セグメントの最大値 ステップ: ステップの長さ、つまり数値セグメントの長さ biz_type: ビジネスタイプ 数値セグメントの取得では、max_id フィールドに対して更新操作 (update max_id = max_id + step) が実行されます。更新が成功した場合、新しい番号セグメントが正常に取得されたことを意味します。新しい数値セグメントの範囲は (max_id, max_id +step] です。 tiny_id_token は、現在のトークンがどのサービスを操作できるかの番号セグメント情報を示す権限テーブルです。 データベースを構成するには、tinyid-server の \offline\application.properties ファイルを変更します。 tinyid はデータベースのマルチマスターモードをサポートしているため、複数のデータベース情報を設定できます。 TinyIdServerApplication を起動してテストします。 - datasource.tinyid.primary.driver-class-name = com .mysql.jdbc.Driver
- datasource.tinyid.primary.url = jdbc :mysql://127.0.0.1:3306/xin-master? です。 autoReconnect = true & useUnicode = true & characterEncoding = UTF -8
- datasource.tinyid.primary.username =ジャンカン
- datasource.tinyid.primary.password =ジャンカン
- datasource.tinyid.primary.testOnBorrow = false
- データソース.tinyid.primary.maxActive = 10
- datasource.tinyid.secondary.driver-class-name = com .mysql.jdbc.Driver
- datasource.tinyid.secondary.url = jdbc :mysql://localhost:3306/db2? です。 autoReconnect = true & useUnicode = true & characterEncoding = UTF -8
- datasource.tinyid.secondary.username =ルート
- データソース.tinyid.セカンダリ.パスワード= 123456
- datasource.tinyid.secondary.testOnBorrow = false
- データソース.tinyid.secondary.maxActive = 10
1. HTTP メソッド Tinyid は、ID と番号セグメントを取得するための合計 4 つの http インターフェイスを提供します。 - パッケージ com.xiaoju.uemc.tinyid.server.controller;
- /**
- * @著者 du_imba
- */
- @レストコントローラ
- @リクエストマッピング("/id/")
- パブリッククラスIdController {
- プライベート静的最終 Logger logger = LoggerFactory .getLogger(IdContronller.class);
- オートワイヤード
- プライベート IdGeneratorFactoryServer idGeneratorFactoryServer;
- オートワイヤード
- プライベートSegmentIdServiceセグメントIdService;
- オートワイヤード
- プライベート TinyIdTokenService tinyIdTokenService;
- @Value("${バッチサイズ最大}")
- プライベート整数batchSizeMax;
- @リクエストマッピング("次のId")
- パブリックレスポンス<リスト<ロング> > nextId(文字列 bizType、整数 batchSize、文字列 token) {
- レスポンス<リスト<ロング> > レスポンス=新しいレスポンス< > ();
- 試す {
- IdGenerator idGenerator = idGeneratorFactoryServer .getIdGenerator(bizType);
- リスト<長い> ids = idGenerator .nextId(newBatchSize);
- レスポンスIDを設定します。
- } キャッチ (例外 e) {
- 応答.setCode(ErrorCode.SYS_ERR.getCode());
- レスポンス.setMessage(e.getMessage());
- logger.error("nextIdエラー", e);
- }
- 応答を返します。
- }
- @RequestMapping("nextIdSimple")
- パブリック String nextIdSimple(String bizType、Integer batchSize、String token) {
- 文字列応答= "" ;
- 試す {
- IdGenerator idGenerator = idGeneratorFactoryServer .getIdGenerator(bizType);
- (新しいバッチサイズ== 1 ) の場合 {
- ロングid = idGenerator .nextId();
- レスポンス= id + "";
- } それ以外 {
- リスト<長い> idList = idGenerator .nextId(新しいバッチサイズ);
- StringBuilder sb =新しいStringBuilder();
- (Long id : idList) の場合 {
- sb.append(id).append(",");
- }
- レスポンス= sb .deleteCharAt(sb.length() - 1).toString();
- }
- } キャッチ (例外 e) {
- logger.error("nextIdSimpleエラー", e);
- }
- 応答を返します。
- }
- @リクエストマッピング("次のセグメントID")
- パブリックレスポンス< SegmentId > nextSegmentId(String bizType, String token) {
- 試す {
- セグメントID segmentId = segmentIdService .getNextSegmentId(bizType);
- レスポンス.setData(セグメントID);
- } キャッチ (例外 e) {
- 応答.setCode(ErrorCode.SYS_ERR.getCode());
- レスポンス.setMessage(e.getMessage());
- logger.error("nextSegmentIdエラー", e);
- }
- 応答を返します。
- }
- @RequestMapping("次のセグメント ID をシンプル")
- パブリック String nextSegmentIdSimple(String bizType, String token) {
- 文字列応答= "" ;
- 試す {
- セグメントID segmentId = segmentIdService .getNextSegmentId(bizType);
- レスポンス= segmentId.getCurrentId () + "," + segmentId.getLoadingId() + "," + segmentId.getMaxId()
- + "," + segmentId.getDelta() + "," + segmentId.getRemainder();
- } キャッチ (例外 e) {
- logger.error("nextSegmentIdSimple エラー", e);
- }
- 応答を返します。
- }
- }
nextId と nextIdSimple は次の ID を取得するために使用され、 nextSegmentIdSimple と getNextSegmentId は次の利用可能なセグメントを取得するために使用されます。違いは、インターフェースに戻りステータスがあるかどうかにあります。 - 次のID:
- 'http://localhost:9999/tinyid/id/nextId? bizType =テスト&トークン= 0f673adf80504e2eaa552f5d791b644c '
- 応答:
- {
- 「データ」: [2],
- 「コード」: 200,
- "メッセージ": ""
- }
- nextId シンプル:
- 'http://localhost:9999/tinyid/id/nextIdSimple? bizType =テスト&トークン= 0f673adf80504e2eaa552f5d791b644c '
- 回答: 3
2. Tinyidクライアント http を使用したくない場合は、Tinyid-client も良い選択肢です。 tinyid-serverパッケージを参照する - <依存関係>
- <グループ ID > com.xiaoju.uemc.tinyid </グループ ID >
- <artifactId> tinyid -クライアント</artifactId>
- <バージョン> ${tinyid.version} </バージョン>
- </依存関係>
tinyid-server プロジェクトを起動し、パッケージ化して tinyid-server-0.1.0-SNAPSHOT.jar を取得します。バージョン ${tinyid.version} を 0.1.0-SNAPSHOT に設定します。 プロジェクトの application.properties で tinyid-server サービスのリクエスト アドレスとユーザー ID トークンを設定します。 - tinyid.server = 127.0.0.1:9999
- tinyid.token = 0f673adf80504e2eaa552f5d791b644c ````
Java コードで TinyId を呼び出すことも非常に簡単で、必要なコードは 1 行だけです。 - // ビジネスタイプに基づいて単一のIDを取得します
- ロングid = TinyId .nextId("test");
- // ビジネス タイプに基づいて 10 個の ID を一括で取得します
- リスト<長い> ids = TinyId .nextId("テスト", 10);
Tinyid プロジェクト全体のソース コードの実装も比較的シンプルです。たとえば、データベースとのやりとりはjdbcTemplateを使用してより直接的に実装されます。 - @オーバーライド
- パブリック TinyIdInfo クエリByBizType(文字列 bizType) {
- 文字列sql = "select id、biz_type、begin_id、max_id、" +
- 「ステップ、デルタ、残り、作成時間、更新時間、バージョン」+
- " tiny_id_info から、 biz_typeは ?";
- <TinyIdInfo> のリスト リスト= jdbcTemplate .query(sql、新しいオブジェクト[]{bizType}、新しい TinyIdInfoRowMapper());
- if(リスト== null || list.isEmpty()) {
- null を返します。
- }
- リストを返します。get(0);
- }
要約する 2つの方法のうち、Tinyid-client が推奨されます。この方法では、ID はローカルで生成されます。ステップ長 (ステップ) が長いほど、サポートされる qps が大きくなります。ステップを十分に大きく設定すると、qps は 1000w 以上に達する可能性があります。さらに、tinyid-client から tinyid-server へのアクセス頻度が低くなるため、サーバーへの負荷が軽減されます。 |