フレームワーク: 分散グローバルユニークID

フレームワーク: 分散グローバルユニークID

[[407823]]

この記事はWeChatの公開アカウント「Sneak Forward」から転載したもので、著者はcscwです。この記事を転載する場合は、Qianxingqianxing の公開アカウントにご連絡ください。

序文

HTTP リクエストが行われ、データベース トランザクションが実行されるたびに、コード実行を追跡するときに、これらのビジネス操作に関連付ける一意の値が必要になります。スタンドアロン システムの場合、データベースの自動増分 ID またはタイムスタンプとローカルに増分された値を使用することで、一意の値を実現できます。しかし、分散システムでは、どうすれば一意の ID を実現できるのでしょうか?

  • 分散IDの特徴
  • データベース自動増分ID
  • Redis 分散 ID
  • Zookeeper 分散 ID
  • グローバルに一意なUUIDの利点と欠点
  • Twitterのスノーフレークアルゴリズムは分散IDを生成する

分散IDの特徴

  • 世界的な独自性、必要性
  • 冪等性: 特定の情報に基づいて生成される場合、冪等性が保証される必要がある
  • セキュリティに注意してください。ID には推測できない情報が隠されており、推測することはできません。 IDを生成する方法
  • トレンド増分、クエリと比較すると、ビジネスオペレーションの時系列を判断できます

データベース自動増分ID

実装はシンプルで、ID は単調増加し、数値型のクエリ速度は高速ですが、シングルポイント DB ではダウンタイムのリスクがあり、高同時実行シナリオに耐えられません。

  1. 作成する テーブルFLIGHT_ORDER (
  2. id int (11) 符号なしNOT   NULL auto_increment、#自動インクリメント ID
  3. 主要な キー(ID)、
  4. )ENGINE=innodb;

クラスター内のデータベースIDの一意性を確保する方法

  • 事業が発展するにつれて、サービスは複数の大規模なクラスターに拡張されます。単一ポイントデータベースの圧迫を解決するために、データベースもそれに応じてクラスター化されます。クラスター内のデータベース ID の一意性を確保するにはどうすればよいですか?
  • 各データベース インスタンスは、開始値と増加ステップ サイズを設定します。

デメリット: その後の拡張には役立ちません。後で拡張が必要になった場合は、開始値と成長ステップを変更するために手動で介入する必要があります。

Redis 分散 ID

システムに数十億のデータがある場合、データベースの自動増分 ID に依存してテーブルとデータベースをシャーディングした後、各データベース インスタンスを手動で変更する必要がありますが、スケーラビリティと保守性が低下します。

Redis INCRコマンドに基づいて分散グローバル一意IDを生成する

  • サービスは Redis から ID を取得し、ID はデータベースから分離されるため、ID とサブテーブルおよびサブデータベースの問題を解決できます。さらに、Redis はデータベースよりも高速であり、クラスター サービスが ID を同時に取得するニーズをサポートできます。
  • redis の INCR コマンドには、INCR AND GET というアトミック操作があります。 redisはシングルプロセス、シングルスレッドのアーキテクチャであり、INCRコマンドはIDの重複を引き起こしません。
  1. オートワイヤード
  2. プライベート StringRedisTemplate stringRedisTemplate;
  3. プライベート静的最終文字列 ID_KEY = "id_good_order" ;
  4. パブリックLong incrementId() {
  5. stringRedisTemplate.opsForValue().increment(ID_KEY)を返します
  6. }

HINCRBY コマンド

  • 実際、シリアル番号に関するより関連性の高い情報を保存するには、Redis のハッシュ データ構造を使用できます。 Redis は、ハッシュに「INCR AND GET」アトミック操作を実装するための HINCRBY コマンドも提供します。
  1. //KEY_NAMEはハッシュ構造に対応するキー、FIELD_NAMEはハッシュ構造のフィールド、INCR_BY_NUMBERは増分値です
  2. redis 127.0.0.1:6379> HINCRBY キー名 フィールド名 INCR_BY_NUMBER

ダウンタイムのシリアル番号回復の問題

  • Redis はインメモリ データベースです。 RDB または AOF の永続性が有効になっていない場合、クラッシュが発生すると ID データが失われます。 RDB 永続性が有効になっている場合でも、最新のスナップショットと最新の HINCRBY コマンドの間に時間差がある場合があり、ダウンタイム後に RDB スナップショットを介してデータセットを復元すると、重複した ID 値が発生する可能性があります。
  • Redis ダウンタイム シーケンス番号回復ソリューション
    • リレーショナル データベースを使用して、短時間で使用可能な最大シーケンス番号 MAX_ID を記録します。 redis から ID を取得する場合、MAX_ID 未満のシーケンス番号のみが取得されます。
    • 最大値を計算するには、ID消費率RATEを定期的に計算し、redisに保存するスケジュールされたタスクが必要です。クライアントは、CUR_ID、RATE、MAX_ID を取得すると、ID 消費率 RATE に基づいて CUR_ID が MAX_ID に近いかどうかを計算します。そうであれば、データベース内の MAX_ID を更新します。

Zookeeper 分散 ID

  • Zookeeper の永続的な順序付きノードを使用することで、自己増分分散 ID を実装できます。 Zookeeper は可用性の高いクラスター サービスであり、正常に送信されたメッセージは永続的であるため、マシンのダウンタイムや単一マシンの問題を心配する必要はありません。
  1. <依存関係>
  2. <グループ ID>org.apache.curator</グループ ID>
  3. <artifactId>キュレーターフレームワーク</artifactId>
  4. <バージョン>4.2.0</バージョン>
  5. </依存関係>
  6. <依存関係>
  7. <グループ ID>org.apache.curator</グループ ID>
  8. <artifactId>キュレーターレシピ</artifactId>
  9. <バージョン>4.2.0</バージョン>
  10. </依存関係>

  1. 再試行ポリシー retryPolicy = 新しい ExponentialBackoffRetry(500, 3);
  2. CuratorFramework クライアント = CuratorFrameworkFactory.builder()
  3. .connectString( "localhost:2181" )
  4. .接続タイムアウトMs(5000)
  5. .セッションタイムアウトMs(5000)
  6. .retryPolicy(再試行ポリシー)
  7. 。建てる();
  8. クライアントを起動します。
  9. 文字列sequenceName = "root/sequence/distributedId" ;
  10. 分散アトミックロング distAtomicLong = 新しい分散アトミックロング(クライアント、シーケンス名、再試行ポリシー);
  11. //DistributedAtomicLongを使用して自動インクリメントシーケンスを生成する
  12. パブリックLongシーケンス() は例外をスローします {
  13. AtomicValue<Long>シーケンス= this.distAtomicLong.increment();
  14. if (シーケンス.succeeded()) {
  15. 戻る シーケンス.postValue();
  16. }それ以外{
  17. 戻る ヌル;
  18. }
  19. }

UUIDの利点と欠点

  • データベース、Redis、Zookeeper に基づく分散 ID はすべて、外部サービスに大きく依存しています。いくつかのシナリオでは、これらの外部サービスが存在しない場合に分散 ID を生成するにはどうすればよいでしょうか?
  • JDK には、グローバルに一意の ID ジェネレーターが付属しています。これは UUID ですが、意味のない文字列であり、ストレージ パフォーマンスが低く、クエリに時間がかかります。注文システムの固有IDとしては適していません。一般的な最適化ソリューションは、「保存用に 2 つの uint64 整数に変換する」か、「半分に保存する」ことです (半分にした後は一意性が保証されません)
  • ただし、ログ記録システムの場合、またはデータ内のシリアル番号を一意に識別できる属性を関連付ける場合は、UUID を使用できます。
  1. 文字列 uuid = UUID.randomUUID().toString().replaceAll( "-" , "" );

Twitterのスノーフレークアルゴリズムは分散IDを生成する

  • UUIDと同様に、スノーフレークアルゴリズムは外部サービスに依存しません。
  • スノーフレークアルゴリズムは、Twitter社内の分散プロジェクトで使用されているID生成アルゴリズムであり、国内企業から高く評価されています。サードパーティのサービスに依存せず、高い効率性

Snowflake ID 構造は、正の数字 (1 ビット) + タイムスタンプ (41 ビット) + マシン ID (5 ビット) + データ センター (5 ビット) + 自動増分値 (12 ビット) の合計 64 ビットの Long 型で構成されます。

1: 最初のビット (1 ビット): Java の long の最上位ビットは符号ビットであり、正または負を表します。正の数は 0、負の数は 1 です。通常、生成される ID は正の数なので、デフォルト値は 0 です。

2: タイムスタンプ部分(41ビット):ミリ秒レベルの時間。現在のタイムスタンプを保存することはお勧めしません。代わりに、(現在のタイムスタンプ - 固定開始タイムスタンプ) の差を使用して、生成される ID が小さい値から開始されるようにします。

3: 作業マシン ID (10 ビット): workId とも呼ばれ、コンピュータ ルームまたはマシン番号の組み合わせで柔軟に構成できます。

4: シーケンス番号部分(12ビット)、自己増分サポート 同じノードから同じミリ秒内に4096個のIDを生成可能

  1. //TwitterのSnowFlakeアルゴリズム、SnowFlakeアルゴリズムを使用して整数を生成する
  2. パブリッククラスSnowFlakeShortUrl {
  3. //開始タイムスタンプ
  4. 静的long START_TIMESTAMP = 1624698370256L;
  5. //各部分が占めるビット数
  6. 静的ロングSEQUENCE_BIT = 12; //シーケンス番号が占めるビット数
  7. 静的ロングMACHINE_BIT = 5; //マシンIDが占めるビット数
  8. 静的ロングDATA_CENTER_BIT = 5; //データセンターが占有するビット数
  9. //各パーツの最大値
  10. 静的ロング MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
  11. 静的ロング MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
  12. 静的ロング MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_BIT);
  13. //各パーツを左にずらす
  14. 静的long MACHINE_LEFT = SEQUENCE_BIT;
  15. 静的long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
  16. 静的long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;
  17. //dataCenterId + machineId は 10 ビットの作業マシン ID に等しい
  18. プライベート長いデータセンターID; //データセンター
  19. プライベートロングマシンID; //マシンID
  20. プライベート揮発性ロングシーケンス= 0L; //シリアルナンバー
  21. プライベート volatile long lastTimeStamp = -1L; //最後のタイムスタンプ
  22. プライベート volatile long l currTimeStamp = -1L; //現在のタイムスタンプ
  23.      
  24. プライベートlong getNextMill() {
  25. ロングミル = System.currentTimeMillis();
  26. mill <= lastTimeStamp の場合、 mill = System.currentTimeMillis();
  27. リターンミル;
  28. }
  29. //指定されたデータセンターIDとマシンIDに基づいて指定されたシリアル番号を生成します
  30. パブリックSnowFlakeShortUrl(longデータセンターId、longマシンId) {
  31. Assert.isTrue(dataCenterId >=0 && dataCenterId <= MAX_DATA_CENTER_NUM, "dataCenterId が不正です!" );
  32. Assert.isTrue(machineId >= 0 || machineId <= MAX_MACHINE_NUM, "machineId が不正です!" );
  33. this.dataCenterId = データセンターId;
  34. this.machineId = マシンID;
  35. }
  36. //次のIDを生成する
  37. パブリック同期された長いnextId(){
  38. currTimeStamp = System.currentTimeMillis();
  39. Assert.isTrue(currTimeStamp >= lastTimeStamp, "時計が逆方向に動きました" );
  40. (カレントタイムスタンプ == ラストタイムスタンプ)の場合{
  41. //同じミリ秒で、シリアル番号が自動的に増加します
  42. シーケンス= (シーケンス+ 1) & MAX_SEQUENCE;
  43. if ( sequence == 0L) { // 同じミリ秒内のシーケンスの数が最大値に達した場合は、次のミリ秒を取得します
  44. currTimeStamp = getNextMill();
  45. }
  46. }それ以外{
  47. シーケンス= 0L; //異なるミリ秒では、シーケンス番号は0に設定されます
  48. }
  49. 最後のタイムスタンプ = currTimeStamp;
  50. return (currTimeStamp - START_TIMESTAMP) << TIMESTAMP_LEFT //タイムスタンプ部分
  51. | dataCenterId << DATA_CENTER_LEFT //データセンター部分
  52. | machineId << MACHINE_LEFT //マシン識別部分
  53. |順序; //シーケンス番号部分
  54. }
  55.      
  56. 公共 静的void main(String[] args) {
  57. SnowFlakeShortUrl snowFlake = 新しい SnowFlakeShortUrl(10, 4);
  58. ( int i = 0; i < (1 << 12); i++) {
  59. //10進数
  60. システム。出力.println(snowFlake.nextId());
  61. }
  62. }
  63. }

参照

[1]GitHubアドレス: https://github.com/cscsss/learnHome

[2] 一般的な分散型グローバルユニークID生成戦略とアルゴリズムの比較:

https://blog.csdn.net/u010398771/article/details/79765836

[3] Redisベースのシリアル番号サービス(分散ID)の設計:

https://blog.csdn.net/carryxu123456/article/details/82630029

[4] 9つの分散ID生成スキームにより、一度に十分な学習が可能:

https://segmentfault.com/a/1190000022717820

<<:  知っておくべき Kafka コンシューマーのパラメーターは何ですか?

>>:  モバイルエッジコンピューティングは爆発的な成長を遂げると予想されている

推薦する

ドメイン名登録の混乱: 個人は予約ドメイン名を繰り返し登録できるが、奪われてしまうこともある

ウェブサイトのドメイン名を登録することはお金を稼ぐための手っ取り早い方法です2007年、動画共有サイ...

ウェブサイトのトラフィックが減少しているのはなぜですか?

月給5,000~50,000のこれらのプロジェクトはあなたの将来ですトラフィックは毎日、毎分、さらに...

racknerd France VPSはいかがでしょうか?測定データの共有

一昨日、Racknerd はフランスの VPS 事業を開始し、プロモーション用に特に安価なフランスの...

エンタープライズネットワークマーケティングはデータから金を掘り出す方法を知る必要がある

インターネットの波の中で、多くの企業、特に一部の電子商取引企業が独自のウェブサイトを構築し、独自のイ...

産業用 IoT を活用してエッジ コンピューティングで競争上の優位性を生み出す方法

モノのインターネットは現在、多くの業界組織にとって不可欠な要素となっており、農業、製造、医療、輸送、...

電気機械産業におけるエントリーレベルのネットワークマーケティング戦略についての簡単な説明

昨日、私は上司から、インターネット マーケティングについて数人の新しい同僚をトレーニングし、同時にイ...

SEO担当者は常に、1つのテーマを持つウェブサイトの方がランキングとユーザーの信頼を獲得する可能性が高いことを覚えておく必要があります。

最近、著者はウェブサイトを構築し、2か月も経たないうちに、Baiduのホームページに「ダイエット薬ラ...

#超高速専用 VPS#: BandwagonHost VPS、10Gbps 帯域幅、香港 CN2/日本 CN2/米国 CN2/カナダ CN2/オランダ CU2/オーストラリア CU2

Bandwagonhost vps: ビジネスで極めて高速なネットワークが必要な場合、最速の海外 v...

観察力と分析力を活用してフォーラムマーケティングを行う方法

フォーラム マーケティングを行うにはどうすればよいでしょうか。どこから始めればよいでしょうか。まずは...

zoic: ロシアの VPS、15 元/1Gbps 帯域幅/無制限トラフィック/512M メモリ/10G ハードディスク

ロシアのホスティング会社である Zoic は、2009 年に設立されました。主な事業は、仮想ホスティ...

投資家の2012年:虎は昼寝をせず、中小企業は苦境に立たされる

2006年から2012年までのVCPE機関のIPO出口の帳簿収益2012年は中国の投資家と起業家にと...

2018年第3四半期のローエンドVPSランキングリスト

今年第3四半期の海外有名ローエンドVPSランキングリストが発表されました。ローエンドVPS業界のボス...

あなたは本当に JVM を理解していますか? JVM のメモリ領域とその機能は何ですか?

1.0 序文前回は、.class ファイルが jvm にロードされる方法について説明しました。しかし...

クラウドとオンプレミスの長所、短所、ユースケース

IT インフラストラクチャに関して、企業はクラウドを完全に採用するか、オンプレミスに留まるかという重...

巨大企業のクラウドコンピューティングの前編:公式の歴史の裏に隠された「浮き沈み」と「不合理」

インターネット大手によるクラウドコンピューティング開発の歴史は、何千回も書き記されてきました。しかし...