使用中によく生じるパフォーマンスに関する質問に答えて、次の 3 つのベスト プラクティスを示します。
❄ ID 生成要件が 5W/s を超えない場合、構成パラメーターを変更する必要はありません。
❄ 5W 個/秒を超え、50W 個/秒未満の場合は、SeqBitLength=10 に変更することをお勧めします。
❄ 50W ビット/秒を超え、500W ビット/秒に近い場合は、SeqBitLength=12 に変更することをお勧めします。
要約すると、SeqBitLength を増やすとパフォーマンスは向上しますが、生成される ID は長くなります。
❄ これは最適化されたスノーフレーク アルゴリズム (スノーフレーク ドリフト) であり、より短く高速な ID を生成します。
❄ k8s などのコンテナ環境の自動拡張(WorkerId の自動登録)をサポートし、スタンドアロン環境または分散環境でデジタル固有 ID を生成できます。
❄ C#/Java/Go/C/Rust/Python/Node.js/PHP (C 拡張)/SQL/ およびその他の言語をネイティブにサポートし、マルチスレッドの安全な動的ライブラリ呼び出し (FFI) を提供します。
❄ すべてのスノーフレーク アルゴリズム (番号セグメント モードまたはクラシック モード、大手メーカーまたは中小企業メーカー) と互換性があるため、将来的にアップグレードまたは切り替えを行うことができます。
❄ これは、コンピューター史上最も包括的な Snowflake ID 生成ツールです。 【2022年8月現在】
? アーキテクトとして、データベース、特に複数のデータベースを備えた分散システムにおける一意の主キーの問題を解決したいと考えています。
? データ テーブルの主キーの使用する記憶域スペースを最小限に抑え、インデックスを高速に作成し、選択、挿入、更新を高速に実行したいと考えています。
? データベースとテーブルを分割する (データベースとテーブルを結合する) 場合、主キーの値が直接使用され、ビジネス タイミングが反映される可能性があることを考慮する必要があります。
? このような主キーの値が長すぎて、フロントエンド js の Number 型の最大値を超える場合は、Long 型を String 型に変換する必要があり、少しイライラします。
? Guid は自動インクリメントできますが、多くのスペースを消費し、インデックス作成の速度が遅くなります。
? アプリケーション インスタンスが 50 を超える場合があり、各同時リクエストは 10W/秒に達する可能性があります。
? コンテナ環境にアプリケーションを展開するには、水平レプリケーションと自動拡張をサポートします。
? 継続的な主キー ID はビジネス データのセキュリティ リスクを引き起こすため、redis の自動インクリメント操作に依存して継続的な主キー ID を取得することは望ましくありません。
? システムを 100 年以上稼働させたいと考えています。
生成された ID が長すぎます。
瞬間的な同時実行の量が十分ではありません。
時刻ダイヤルバックの問題は解決できません。
事前注文 ID の補足後の生成はサポートされていません。
外部ストレージ システムに依存する場合があります。
✔ 整数。時間の経過とともに単調に増加し (連続的である必要はない)、長さが短く、50 年間で js Number タイプの最大値を超えることはありません。 (デフォルト構成)
✔ 従来のスノーフレーク アルゴリズムよりも 2 ~ 5 倍高速で、0.1 秒で 500,000 個を生成できます (第 8 世代の低電圧 i7 に基づく)。
✔ 時間コールバック処理をサポートします。たとえば、サーバー時間が 1 秒戻された場合、このアルゴリズムは自動的に適応して重要な時間の一意の ID を生成できます。
✔新しい ID の手動挿入をサポートします。過去の時点で企業が新しい ID を生成する必要がある場合、このアルゴリズムの予約ビットにより 1 秒あたり 5,000 ID を生成できます。
✔ 外部キャッシュやデータベースに依存しません。 (k8s環境にWorkerIdを自動登録する動的ライブラリはredisに依存しています)
✔基本的な機能。すぐに使用でき、設定ファイルやデータベース接続などは必要ありません。
(パラメータ: 10 ビット自動増加シーケンス、1000 ドリフト最大値)
継続的なリクエスト | 5K | 5W | 50W |
---|---|---|---|
従来のスノーフレークアルゴリズム | 0.0045秒 | 0.053秒 | 0.556秒 |
雪の漂流アルゴリズム | 0.0015秒 | 0.012秒 | 0.113秒 |
? 究極のパフォーマンス: 500W/秒〜3000W/秒。 (すべてのテストデータは第 8 世代低電圧 i7 に基づいて計算されています)
? システム時間がダイヤルバックされると、アルゴリズムは過去の時系列の予約されたシーケンス番号を使用して新しい ID を生成します。
? コールバックによって生成された ID 番号はデフォルトで最初に配置されますが、後に配置されるように調整することもできます。
? 時間をこのアルゴリズムのプリセットベースに戻すことができます (パラメータは調整可能です)。
? このアルゴリズムによって生成される ID は整数です (最大 8 バイトのスペースを占有します)。以下は、デフォルト設定に基づいて生成される ID です。
129053495681099 (运行1年,长度:15)
387750301904971 (运行3年,长度:15)
646093214093387 (运行5年,长度:15)
1292658282840139 (运行10年,长度:16)
9007199254740992 (运行70年,达到 js Number 最大值,长度:16)
165399880288699493 (运行1000年,等同普通雪花算法运行1年,长度:18)
このアルゴリズムで生成される ID 値は、js Number の最大値の 1% ~ 10% であり、通常のスノーフレーク アルゴリズムの 1,000 分の 1 の値ですが、生成速度は通常のスノーフレーク アルゴリズムよりも高速です。
? js Number タイプの最大値: 9007199254740992。このアルゴリズムでは、同時実行パフォーマンス (5W+/0.01s) と最大 64 WorkerId (6bit) を維持しながら、js Number Max 値に到達するまでに 70 年かかる可能性があります。
? 每增加 1位 WorkerIdBitLength 或 SeqBitLength,生成的ID数字值将会乘以2(基础长度可参考前一节“ID示例”),反之则除以2。
使用可能期間の説明は、生成される ID 番号が long の最大値 (符号付き 64 ビット、8 バイト) を超えるまでに成長する可能性がある場合を指します。
• デフォルト構成では、71000 個の一意の ID を使用できます。
? 1024 個のワーカー ノードをサポートする場合、ID は重複することなく 4480 年間使用できます。
? 4096 個のワーカー ノードをサポートする場合、ID は重複することなく 1120 年間使用できます。
❄ WorkerIdBitLength 、マシンコードのビット長は、WorkerId の最大値を決定します。デフォルト値は 6 で、値の範囲は [1, 19] です。実際、一部の言語では、受信に unsigned ushort (uint16) 型が使用されます。このパラメータは有効であるため、最大値は 16 です。signed short (int16) が使用されている場合、最大値は 15 です。
❄ WorkerId 、マシン コード、最も重要なパラメータ、デフォルト値なし、グローバルに一意である必要がある (または同じ DataCenterId 内で一意である)、プログラムで設定する必要がある、デフォルト条件 (WorkerIdBitLength がデフォルト値を取る)、最大値は 63、理論上の最大値は 2^WorkerIdBitLength -1 です (異なる実装言語では 65535 または 32767 に制限される場合があります。原理は WorkerIdBitLength ルールと同じです)。異なるマシンまたは異なるアプリケーション インスタンスで同じ値を設定することはできません。アプリケーションを通じてこの値を設定することも、外部サービスを呼び出して値を取得することもできます。 WorkerId の自動登録のニーズに応えて、このアルゴリズムはデフォルトの実装を提供します。つまり、redis を介して WorkerId の動的ライブラリを自動的に登録します。詳細については、「ToolsAutoRegisterWorkerId」を参照してください。
特記事項: サーバーが複数の独立したサービスをデプロイする場合は、サービスごとに異なる WorkerId を指定する必要があります。
❄ SeqBitLength 、シーケンス ビット長、デフォルト値 6 、値の範囲 [3、21] (4 以上を推奨) は、ミリ秒ごとに生成される ID の数を決定します。 1 秒あたりのリクエスト数が 5W を超えない場合は、デフォルト値の 6 をそのまま使用します。5W を超え、50W を超えない場合は、10 以上の値を割り当てることをお勧めします。ルール要件: WorkerIdBitLength + SeqBitLength は 22 を超えてはなりません。
❄ MinSeqNumber 、最小シーケンス番号、デフォルト値 5、値の範囲 [5, MaxSeqNumber]、ミリ秒あたりの最初の 5 つのシーケンス番号は、0 ~ 4 の数字に対応し、予約ビットであり、そのうち 1 ~ 4 は時間ダイヤルバックに対応する予約ビットです。 、0 は手動の新しい値用の予約ビットです。
❄ MaxSeqNumber 、最大シーケンス番号、設定範囲は [MinSeqNumber, 2^SeqBitLength-1]、デフォルト値は 0、実際の最大シーケンス番号は、0 でない場合は最大値 (2^SeqBitLength-1) です。これは実際の最大シーケンス番号であり、複数のマシンが WorkerId を共有してセグメント内の ID を生成しない限り、通常は設定する必要はありません (この場合、最小シーケンス番号を正しく設定する必要があります)。
❄ BaseTime 、ベース時間 (基点時間、原点時間、エポック時間とも呼ばれる) は、デフォルト値 (2020) を持ち、ミリ秒のタイムスタンプ (整数、.NET は DatetTime 型)、その機能は次のとおりです。 ID生成時 システム時刻と基準時刻の差分(ミリ秒)をID生成時のタイムスタンプとして使用します。通常、基準時間を設定する必要はありません。デフォルト値が古すぎると思われる場合は、リセットできます。ただし、今後はこの値を変更しないことをお勧めします。
2 番目のバージョンではパラメータを追加する予定です。
❄ DataCenterId 、データセンター ID (コンピューター室 ID、デフォルトは 0)、グローバルに一意であることを確認してください。
❄ DataCenterIdBitLength 、データセンター ID の長さ (デフォルトは 0)。
❄ TimestampType 、タイムスタンプのタイプ (0 ミリ秒、1 秒)、デフォルトは 0。
1️⃣ シングルトンモードで呼び出します。このアルゴリズムでは単一のスレッドを使用して ID を生成し、複数の当事者からの呼び出しは相互に排他的になります。同じアプリケーション インスタンス内で、呼び出し元はマルチスレッド (または並列) を使用してこのアルゴリズムを呼び出しますが、ID 出力速度は向上しません。
2️⃣ 一意の WorkerId を指定します。 WorkerId のグローバルな一意性は外部システムによって保証され、このアルゴリズムのエントリ パラメータに割り当てられる必要があります。
3️⃣ 単一マシンに複数のインスタンスをデプロイする場合は、異なる WorkerId を使用します。すべての実装がプロセス間の同時一意性をサポートしているわけではありません。念のため、同じホストに複数のアプリケーション インスタンスをデプロイする場合は、各 WorkerId が一意であることを確認してください。
4️⃣ 例外処理。アルゴリズムはすべての例外をスローします。外部システムは例外をキャッチして適切に処理し、大規模なシステム クラッシュの発生を回避する必要があります。
5️⃣ IdGeneratorOptions の定義をよく理解してください。これは、このアルゴリズムの統合と使用に役立ちます。
6️⃣ 雪の漂流アルゴリズムを使用します。コードには従来のスノーフレーク アルゴリズムの定義が含まれており、エントリ ポイントで (Method=2) を指定して従来のアルゴリズムを有効にすることができますが、それでもスノーフレーク ドリフト アルゴリズム (Method=1、デフォルト) を使用することをお勧めします。 、結局のところ、ストレッチ性が高く、パフォーマンスが高くなります。
7️⃣ コアアルゴリズムを変更しないでください。このアルゴリズムには多くの内部パラメータと複雑なロジックが含まれており、コア ロジックを習得していない場合は、多数の綿密で科学的なテストを通じて検証されていない限り、コア コードを変更して運用環境で使用しないでください。
8️⃣ アプリケーション ドメイン内の構成ポリシーは同じです。システムが一定期間実行されており、プロジェクトがプログラムによる WorkerId の指定から WorkerId の自動登録に切り替える必要がある場合は、同じアプリケーション ドメインで使用されているすべてのインスタンスが一貫した構成戦略を採用していることを確認してください。これは WorkerId に限ったことではありません。ですが、他の構成パラメータも含まれます。
9️⃣ サーバー時間を適切に管理します。 Snowflake アルゴリズムはシステム時刻に依存します。オペレーティング システム時刻を手動で大幅に調整しないでください。調整する必要がある場合は、サービスを再度開始するときのシステム時刻が、最後にシャットダウンされた時刻よりも大きくなっているようにしてください。 (注: ワールドクラスまたはネットワークレベルの時刻同期やコールバックによって引き起こされるシステム時刻の小さな変化は、このアルゴリズムには影響しません)
構成の変更とは、システムを一定期間実行した後に動作パラメータ (IdGeneratorOptions オブジェクトのプロパティ) を調整することを指します。
1. 最初の原則は、生成される ID 値が過去の最大値よりも大きくなるように、BaseTime は古いもののみであり、時間の重複や重複した ID が生成されないようにするというものです。 [ システムの実行後に BaseTime を調整することはお勧めできません]
2. WorkerIdBitLength または SeqBitLength を増やすことはいつでも許可されますが、将来生成される ID が古い設定と同じになる可能性があるため、「減少」操作は注意して使用する必要があります。 [システムの実行後に xxxBitLength 値を増加できるようにする]
? 3. WorkerIdBitLength または SeqBitLength のいずれかを減らす必要がある場合は、2 つの新しい xxxBitLength の合計が古い値の合計より大きくなければならないという条件を満たす必要があります。 [実行後に BitLength 値を狭めることは推奨されません]
4. 上記の 3 つのルールは、このアルゴリズムでは論理的に制御されません。ユーザーは、新しい構成が要件を満たしていることを確認した後で構成を変更する必要があります。
? 一意の ID ジェネレーターは WorkerId に依存します。ビジネス サービスが水平方向の無差別レプリケーション (自動拡張) を必要とする場合、一意の ID を生成する前にグローバルに一意の WorkerId を自動的に登録する機能が必要です。
このアルゴリズムは、k8s などのコンテナー環境で Redis を介して WorkerId を自動的に登録できるオープンソースの動的ライブラリ (Go 言語で実装) を提供します。
? Redis を介して WorkerId を登録することが唯一の方法ではありません。集中型構成サービスを開発することもできます。各エンドポイント サービスが開始されると、中央サービスを通じて一意の WorkerId が取得されます。
もちろん、サービスを自動的に拡張する必要がない場合は、WorkerId を自動的に登録する必要はありませんが、グローバルに一意の値を設定します。
? 各エンドポイント サービスに使用可能な ID を (単一またはバッチで) 生成する集中 ID 生成サービスを開発するなど、さまざまな方法があります。
画像リンク: https://github.com/yitter/IdGenerator/blob/master/Tools/AutoRegisterWorkerId/regprocess.jpg
ソースコードのパス:/Go/source/regworkerid/reghelper.go
ダウンロードリンク: https://github.com/yitter/IdGenerator/releases/download/v1.3.3/workeridgo_lib_v1.3.3.zip
// 注册一个 WorkerId,会先注销所有本机已注册的记录
// address: Redis连接地址,单机模式示例:127.0.0.1:6379,哨兵/集群模式示例:127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382
// password: Redis连接密码
// db: Redis指定存储库,示例:1
// sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster,非哨兵模式传入空字符串即可
// minWorkerId: WorkerId 最小值,示例:30
// maxWorkerId: WorkerId 最大值,示例:63
// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数),推荐值15
extern GoInt32 RegisterOne(char* server, char* password, GoInt32 db, char* sentinelMasterName, GoInt32 minWorkerId, GoInt32 maxWorkerId, GoInt32 lifeTimeSeconds);
// 注销本机已注册的 WorkerId
extern void UnRegister();
言語 | ギットハブ |
---|---|
?C# | 例を見る |
?ジャワ | 例を見る |
?行く | 例を見る |
? さび | 例を見る |
?パイソン | 例を見る |
?C | 例を見る |
? C (PHP 拡張子) | 例を見る |
デルフィ(パスカル) | 例を見る |
JavaScript | 例を見る |
?TypeScript | 例を見る |
?V | 例を見る |
?D | 例を見る |
オープンソースのアドレス: https://github.com/yitter/IdGenerator
QQグループ: 646049993