ユニークIDは、次の3つの方法についての多くの一般的な方法があり、分散システム・ソリューションにユニークなIDを生成するための固有の識別データであってもよいです。
- など付加的な配列からのOracleやMySQLなどの依存性データベース、
- UUID乱数
- スノーフレークスノーフレークアルゴリズム
まず、データベースプログラムの不備やUUID
データベースの増分シーケンスを使用します:
- 別個の読み出しと書き込み、のみマスタノードが書き込むことができる場合、単一障害点のリスクがあるかもしれません
- サブテーブルや倉庫、データ移行、統合およびそんなにトラブル
UUID乱数:
- 無意味な文字列を使用して、ソートされていません
- データクエリ効率の量が比較的低い場合UUIDストリングは、記憶されています
第二に、雪のアルゴリズムに
自然が存在しないことを言って二つの同一の雪片があります。それぞれの雪片は美しいとユニークな独自の形状を有しています。雪はまた、アルゴリズムは雪の結晶のようなユニークなIDを生成していると述べました。
1.組成構造
一般的に含む:SEQ ID NO組成物をコードする第一の無効な文字、4つの部分にタイムスタンプ差、機械(プロセス)
2.特徴(インクリメント、秩序及び分散シナリオに適し)
- 時間位置:それは、検索までの時間と助け速度に応じて並べ替えることができます
- IDビットマシンがマルチノード識別子の分散環境の各ノードに適用される具体的ビットノードと配備に記載の機械10の長さを分割するように設計することができるように等5ビット、の工程分割
- SEQ IDビット:自己増力IDの系列である、同じノードIDを複数生成するミリ秒の同じ数をサポートすることができ、各サポートノード用の12ビットのシーケンス番号カウンタがID番号ごとに4096ミリ秒を生成
スノーフレークアルゴリズムは、特定のプロジェクトだけでなく、自分のニーズに応じて変更することができます。
第三に、アルゴリズムの雪の欠点
スタンドアロンシステムのIDで雪のアルゴリズムが増加しているが、マルチノード分散システムの場合には、クロックはすべてのノードが完全に同期されていないことを保証するものではありません、世界的な増加が表示されますではないことも可能です。
第四に、アルゴリズムの雪を実装するコード
パッケージcom.lw.coodytest.snawflake; / ** * @Classname SnakeFlake * @descriptionはTwitterで、アルゴリズム雪のエネルギー自給IDスノーフレーク(Javaの)分散 (各セクションで-間隔)*スノーフレーク以下の構造を:<BR> * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 0000000000から000000000000 <BR> 長い基本的なタイプはJavaで署名されたように、最上位ビットは符号ビット、0は正数であり、* 1ビットの識別子、負の数は、IDので、一般的に、1 0 <BR>正の数であり、最上位ビットである * 41カット時間(ミリ秒)、現在時刻の41倍の断面ストレージカットオフ時間よりも注目されているが、現在時刻カットオフ(切り捨て蓄積時間との差-カットの開始時刻) *得られた値)、私たちのプログラムで指定された私たちは、IDジェネレータを使用して起動切り捨てられ、一般的に時間、(次のプログラムIdWorkerクラスは以下のstartTime属性)の開始時刻。 * 41カット時間で、69年を使用することができる= T(1L << 41である)/(1000L * 60 * 60 * 24 * 365)= 69 <BR> * 10ビットデータ・ビット・マシン1024に配備することができます5 datacenterId <BR> 5 workerId含むノード、および ミリ秒以内* 12シーケンスカウント、12ミリ秒ごとにID番号4096を生成するために、各サポートノードのシーケンス番号(同じマシン、同じカットオフ時間)をカウント< BR> *ロングタイプのためだけで64まで追加。<BR> *スノーフレークの利点は、時間順に、その全体的な増加であり、衝突を生成しない分散システム全体ID(データセンターのIDと機器IDとは区別されるように)、高効率、 毎秒*試験は、スノーフレークとすることができます26万IDについて生み出します。 @author LW * * @date 2020年3月17日14:21 * / パブリック クラスSnowflakeIdWorker { / ** *開始時刻カット * / プライベート 静的 最終 ロング 1420041600000Lを= twepoch ; / ** *ビットの数は、マシンIDによって占有 * / プライベート 静的 最終 ロング workerIdBits = 5L ; / ** *占有データ・ビットを識別するID * / プライベート 静的 最終 ロング datacenterIdBits = 5L ; / ** *最大マシンIDのサポートは、結果は31である(迅速に表すことができるいくつかの小数進数の最大数を計算することができ、このシフトアルゴリズム) * / プライベート 静的 最終 ロング maxWorkerId -1L = ^(-1L << workerIdBitsを); / ** *最大データ識別ID、31結果である * / プライベート 静的 最終 長い maxDatacenterId -1Lは= ^(-1L << datacenterIdBits); / ** *配列番号中央値に占める * / プライベート 静的 最終 長い sequenceBits = 12L ; / ** *左にマシンID 12 * / プライベート 静的 最終 長い workerIdShift = sequenceBits; / ** * 17によって左にID識別データ(+ 12は5である。) * / プライベート 静的 最終 ロング datacenterIdShift + = sequenceBitsのworkerIdBits; / ** 22を左カットする*時間(5 + + 12は5である。) * / プライベート 静的 最終 ロング workerIdBits + + = sequenceBits timestampLeftShift datacenterIdBits; / ** *生成するマスクシーケンス、ここでは4095(= 0xFFF = 4095 0b111111111111) * / プライベート 静的 最終 長い sequenceMask -1L = ^(-1L << sequenceBits); / ** *作業機のID(0〜31) * / プライベート ロングworkerId; / ** *データセンターのID(0〜31) * / プライベート ロングdatacenterId; / ** *ミリ秒のシーケンス(0〜4095) * / プライベート ロングシーケンス= 0L ; / ** *時間カット以前に生成されたID * / プライベート ロング LastTimestamp = -1L ; / ** *コンストラクタ * * @param workerIdジョブID(〜31は0である) * @param datacenterIdデータセンタID(〜31 0) * / 公共 SnowflakeIdWorker(ロング workerId、ロングdatacenterId){ IF(workerId> maxWorkerId || workerId <0 ){ スロー 新しい、IllegalArgumentExceptionを(String.Formatのは、( "労働者Idは%dまたは未満0より大きくすることはできません" 、maxWorkerId)); } であれば(datacenterId> maxDatacenterId || datacenterId <0 ){ スロー 新しい、IllegalArgumentExceptionを(String.Formatのは、( "データセンターIdは%dよりも大きいかまたは0未満にすることはできません" )、maxDatacenterId)を、 } この .workerId = workerId。 この .datacenterId = datacenterId。 } / ** *获得下一个ID(该方法是线程安全的) * * @return SnowflakeId * / 公共 同期 ロングNEXTID(){ ロングタイムスタンプ= TIMEGEN(); // 現在の時刻を通って送出されなければならないシステム・クロックのバックオフ時間を示す、以下最後の世代IDのタイムスタンプよりもあれば IF(タイムスタンプ< LastTimestamp){ スロー 新しい新規のAのRuntimeException( String.Formatのは、(「クロック%のDミリ秒を生成することを拒否するための下位IDを動かし。」、LastTimestamp - タイムスタンプ)); } // それが同時に発生した場合は、シーケンスはミリ秒以内に行われる IF(LastTimestamp == タイムスタンプ){ 配列 = (シーケンス+ 1)&sequenceMask; // ミリ秒シーケンスオーバーフロー IF(配列== 0){ // 新しいタイムスタンプを取得し、次のミリ秒ブロッキング タイムスタンプ= ; tilNextMillis(LastTimestamp) } } // リセットシーケンスミリ秒、タイムスタンプの変更を 他{ シーケンス = 0L ; } // 最後に生成されたIDはカット LastTimestamp = タイムスタンプ; // 戦いへのシフトと論理和が一緒になって、64ビットのID形式 リターン((タイムスタンプ- twepoch)<< timestampLeftShiftを) |(datacenterId << datacenterIdShift) |(workerId << workerIdShift) | 配列; } / ** *次ミリ秒、新しいタイムスタンプまでブロック * * @param 断面IDを生成LastTimestamp前回 * @return 現在のタイムスタンプは、 * / 保護 ロング tilNextMillis(ロングLastTimestamp){ ロングタイムスタンプ= TIMEGEN(); 一方、(タイムスタンプ<= LastTimestamp){ タイムスタンプ = TIMEGEN(); } 戻りタイムスタンプ; } / ** *ミリ秒単位で現在の時刻を返す * * @return 現在の時間(ミリ秒) * / 保護 ロングtimeGenは(){ 戻りのSystem.currentTimeMillisを(); } パブリック 静的 ボイドメイン(文字列[]引数){ SnowflakeIdWorker idWorker = 新しい SnowflakeIdWorker(0、0 ); 以下のために(INT I 0 =; I <1000; I ++ ){ 長い ID = idWorker.nextId()。 System.out.println(Long.toBinaryString(ID))。 System.out.println(ID)。 } } }