(1)IDでデータベースから
これは、IDを取得するたびに、あなたのシステムは、データの小さなビジネス上の意味のライブラリにテーブルを挿入し、データベースのID増分を取得することであることを意味します。そして、サブサブライブラリーテーブル書き込み、外出先に対応するIDを取得するために下ります。
この方式の利点は、便利で簡単で、誰が使用されます。欠点は、単一のライブラリ生成インクリメントIDということで、高い同時実行は、その後、ボトルネックがあるだろう場合、あなたは、単に外観を向上させたい場合は、その後、すべての本サービスからサービスをオープンしました倍の最大電流IDを取得して、自分自身のいくつかの増分のID、ワンタイム・リターンのID番号を、その後、増分、いくつかのIDの後に値を現在の最大ID値を修正する。しかし、単一のデータベースに基づいていますどのようにハードに関係なく。
適切なシーン:二つの理由で、あなたのサブライブラリーのサブテーブル、いずれかの単一のデータベースの同時実行性が高すぎるか、あるいは単一のライブラリのデータが大きすぎる;あなたの同時実行性は高くありませんが、データの量は、サブライブラリーのサブテーブルに大きすぎない限り、それは、ライブラリとテーブルの自動インクリメントの主キーを生成するために、放置、その後、数百に第2のアップあたりの最高によって複雑にすることができるので拡大は、あなたは、このプログラムを使用することができます。
同時実行は、数百/ sの非常に低いですが、大量のデータ、データの十億、あなたは膨大な量のデータを格納するためのサブライブラリーのサブテーブルに依存する必要があります
(2)UUID
利点は来ていないデータベースに基づいて、ローカルで生成され、悪い所は、主キーに適した主キーパフォーマンスの悪い、ではないとして、UUIDが長すぎます。
適切なシーン:あなたは、ランダムに生成されたファイル名、番号等に欲しいものであれば、あなたはUUIDを使用することができますが、主キーのUUIDのとして使用することはできません。
UUID.randomUUID()のtoString()を置き換える。。(「 - 」、「」) - > sfsdf23423rr234sfdaf
(3)現在のシステム時刻を取得します
これは、現在の時刻を取得することですが、問題は、このような1秒同時何千もの高い同時実行は、事態の繰り返しがあるだろうと、これは確かに適切ではないということです。基本的には考えられなかったでしょう。
適切なシーン:あなたは、一般的にこのプログラムを使用する場合は、現在の時間は、あなたが考えるビジネスが受け入れ可能である場合、また可能である、IDとして、一緒にスプライス他の多くの事業分野です。あなたは、グローバルに一意のシリアル番号、注文番号、タイムスタンプ、ユーザID + +コーディングビジネス上の意味を形成するために一緒にスプライシングされた現在の時刻とのビジネスフィールドの値を平準化することができます
(4)スノーフレークアルゴリズム
TwitterのIDオープン分散生成アルゴリズムは、長いタイプIDは、12ビットのシーケンス番号であり、41は作業機IDが10ビットで、数ミリ秒として、その中に使用されるビット、64ビット、1ビットを使用しないで
1ビット:ないので、なぜそれから?最初のビットにバイナリが1であるので、それがある場合、それは負であるが、我々は、IDを生成する正であるので、最初のビットが0に均一です
41ビット:それは、タイムスタンプ(ミリ秒)ことを示しています。41ビット数は、最大2 ^ 41--1で表すことができる、すなわち2 ^ 41--1ミリ秒の値を識別することができる、成人、69歳で表します。
10ビット:作業機IDを記録、サービス、すなわち1024機械最大2 ^ 10のマシンに展開することができ表します。しかし、5ビットの10ビット代わっ室IDで、マシンIDの代わりに5のGeビット。2 ^ 5代表的な部屋(部屋32)、及び各まで部屋機2 ^ 5(32機)を表してもよいことを意味します。
12ビット:これはミリ秒以内に生成された異なるIDと共に記録するために使用される最大12ビット= 4096 2 ^ 12--1の正の整数を表すことができる、すなわち、この数は同じ12ビットを区別するために使用することができ、ミリ秒で表さ4096異なるID
long型の64ビットID、64ビット長 - >バイナリ
0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000
2018年1月1日10時00分00秒 - >バイナリに変換し、いくつかの計算を行って、そして、41bitを置く - > 0001100 1,010,001,010,111,110 1,000,100,101,011,100 00
ルームID、17 - > 10001 - >バイナリに変換
マシンID、25 - > 11001 - >バイナリに変換しました
スノーフレークアルゴリズムサービス現在の要求が機械25のエンジンルーム17である場合、それは最初の要求である場合に、、、、時間に2175年11月7日12時12分14秒ポイントによって送信された第1の要求をどのように決定します
2175年11月7日12時12分14秒時点で、機械室25の17は、第2のメッセージ、スノーフレークアルゴリズムのサービスを、送信、と仮定すると、25の機械室17があります2175年11月7日12に、言いました:ミリ秒単位の12時14分時点では前に、この時点で私は追加することができ、同じ部屋、同じマシンは、同じミリ秒で、再び必要なIDを生成します場合は、この時点で、IDの上に生成されて1
0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000001
例えば、我々は、上記の典型的な64ビットIDバイナリであることを観察し、小数が910499571847892992に変換されます。
パブリッククラスIdWorker {
プライベート長いworkerId。
プライベート長いdatacenterId。
プライベート長いシーケンス。
公共IdWorker(長いworkerId、長いdatacenterId、長いシーケンス){
workerId用//健全性チェック
//ここにビットをチェックしないように、あなたがエンジンルーム内に渡されたことを必要とし、マシンID idが0以上で、32を超えることはできません
(workerId> maxWorkerId || workerId <0)であれば{
新しいIllegalArgumentExceptionをスローし(String.Formatのは(、maxWorkerId) "労働者Idは%dまたは未満0より大きくすることはできません");
}
(datacenterId> maxDatacenterId || datacenterId <0)であれば{
新しいIllegalArgumentExceptionをスローし(String.Formatのは(、maxDatacenterId) "データセンターIdは%dまたは未満0より大きくすることはできません");
}
System.out.printf( "ワーカー出発。タイムスタンプ左シフト%dは、データセンターのIDビット%dは、作業者IDビット%dは、配列は%D、workerid%dのビット"、
timestampLeftShift、datacenterIdBits、workerIdBits、sequenceBits、workerId)。
this.workerId = workerId。
this.datacenterId = datacenterId。
this.sequence =配列;
}
プライベート長いtwepoch = 1288834974657L。
プライベート長いworkerIdBits = 5L;
プライベート長いdatacenterIdBits = 5L;
プライベート長いmaxWorkerId = -1L ^(-1L << workerIdBits); //これはバイナリ操作であり、わずか5ビットは31桁までであり、それは、マシンID内言うことである32以下であります
//これは意味の範囲内で、ある5ビットしかできないだけで部屋番号32まで、最大31桁の数字を持っている。民間長いmaxDatacenterId = -1L ^(-1L << datacenterIdBits)
プライベート長いsequenceBits = 12L;
プライベート長いworkerIdShift = sequenceBits。
プライベート長いdatacenterIdShift = sequenceBits + workerIdBits。
プライベート長いtimestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits。
プライベート長いsequenceMask = -1L ^(-1L << sequenceBits)。
プライベート長いlastTimestamp = -1L;
公衆ロングgetWorkerId(){
workerIdを返します。
}
公衆ロングgetDatacenterId(){
datacenterIdを返します。
}
公衆ロングgetTimestamp(){
System.currentTimeMillisを返します();
}
パブリック同期長いNEXTID(){
//ここでは、ミリ秒単位で現在のタイムスタンプを取得することです
長いタイムスタンプ= timeGen()。
IF(タイムスタンプ<lastTimestamp){
System.err.printf( "クロックは%Dまで要求を拒否後方に移動している。"、lastTimestamp)。
(String.Formatのは、(「時計が後方に移動しました。%d個のミリ秒単位のidを生成するために拒否」の新しいのRuntimeExceptionをスローし、
lastTimestamp - タイムスタンプ));
}
// 0
//同じミリ秒であり、IDを生成するための要求を送信し、0 - > 1
IF(lastTimestamp ==タイムスタンプ){
シーケンス=(シーケンス+ 1)&sequenceMask;これはミリ秒以内までしか4096個の番号を持つことができ、関係なく、あなたが渡されたどのくらい、この場所は常に4096で、この範囲を動作を保証しないことを意味し、//、あなたが転送を避けます4096を超える範囲のこのシーケンス
IF(配列== 0){
タイムスタンプ= tilNextMillis(lastTimestamp)。
}
}他{
シーケンス= 0;
}
//ここでは、最新のIDに関する記録はミリ秒単位でタイムスタンプを生成しました
lastTimestamp =タイムスタンプ。
//ここでは41ビットに、左をスタンプすることがあり、IDが5ビット部屋に左、IDが5ビットマシンに残され、最後のシーケンス番号は10ビットを配置;スプライシングさ最終まで64ビットの2進数、10進long型に変換されます。
リターン((タイムスタンプ - twepoch)<< timestampLeftShift)|
(datacenterId << datacenterIdShift)|
(workerId << workerIdShift)|
配列;
}
0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000
プライベート長いtilNextMillis(ロングlastTimestamp){
長いタイムスタンプ= timeGen()。
一方、(タイムスタンプ<= lastTimestamp){
タイムスタンプ= timeGen()。
}
タイムスタンプを返します。
}
プライベート長いtimeGen(){
System.currentTimeMillisを返します();
}
// --------------- ---------------テスト
パブリック静的無効メイン(文字列[] args){
IdWorkerワーカー=新しいIdWorker(1,1,1);
{(; iが30 <I ++はiが0 = INT)のために
System.out.println(worker.nextId())。
}
}
}
あなたはどのように言うか、それの意味について、それは41ビットで、ミリ秒単位での現在のタイムスタンプで、それはこの意味である。そして、5ビットは5ビット、あなたが部屋のIDで(だけ32の最大以内)に合格したことですあなたは前世代に従うならば、あなたのマシンが(だけで最大32以内)のidで渡され、10ビットのシリアル番号の残りの部分は、つまり、時間のミリ秒のIDの中に残っている場合、注文は、あなたが蓄積与えます未満4096個の番号まで。
ですから、彼はサービスに従事するツールを活用し、各部屋内の各マシンの機械室のシリアル番号の先頭が0である、そのようなことを初期化されます。そして、それは機械室は、IDを生成することを言って、リクエストを受信するたびに、対応する労働者、世代を見つけるでしょう。
彼のアルゴリズムは時間を生成し、これはミリ秒単位で現在の41ビットを置く、次いで室温シーケンス番号と同じでない場合、自動的からの時間に生成された決意番号に続く5ビットのID、ID 5ビットマシンでありますゼロ、最後の時間になりましたかミリ秒内であれば、彼はつまり、自動的にミリ秒単位の異なる番号を生成する、1つインクリメント配列を取りました。
4096まで生成し、すべての部屋には、各マシンごとにミリ秒を確保するために、と言うことができるアルゴリズムがIDで繰り返されていません。
このアルゴリズムスノーフレークを使用して、あなたも機械室とIDのIDの、とにかく、あなたはさておき5ビット+ 5ビットを設定し、あなたが可能であり、他のものに意味をビジネスを持って、あなた自身の会社のサービスを開発することができます。
、通常は数十秒あたりの同時シーンの何千もの、それは高い同時実行であれば、これは比較的良好なパフォーマンスがどうあるべきか、あなたと十分なスノーフレークアルゴリズムはまだ比較的トリッキーなので、あなたが本当にID分散型発電を行う必要がありますA。