分散型のユニークなIDの増分(雪のアルゴリズム)

スノーフレーク(雪の結晶)アルゴリズム。

 


デフォルトでは、41bitのタイムスタンプがにアルゴリズムの使用をサポートすることが2082 年、10ビット作業機のIDができる
サポート1024 マシンを、SEQ ID NO支援1 生成ミリ秒4096 の広告に増加するシーケンスの一つのID。スノーフレークの利点は、全体の
時間の上半身インクリメントソート、全体分散システム生成しないIDの衝突データセンタID 、マシンID
区別のため試験、および高効率を、スノーフレークはごとに生成することができる26で百万ID 周り

パブリック クラスSnowflakeIdWorker {
     / ** 時間カットを開始(2015年1月1日)* / 
    プライベート 最終 ロング twepoch = 1489111610226L ; 
 
    / ** マシンIDによって占められるビットの数* / 
    プライベート 最終 ロング workerIdBits = 5L ; 
 
    / ** 識別データ桁のIDを共有* / 
    プライベート 最終 ロング dataCenterIdBits = 5L ; 
 
    / ** サポートされる最大のマシンIDが、結果は31である(迅速に表すことができるいくつかの小数進数の最大数を計算することができ、このシフトアルゴリズム)* / 
    プライベート 最終 ロング maxWorkerId -1L = ^(-1L << workerIdBits); 
 
    / ** 最大データ識別ID、結果は31であります* /
    民間 最終 ロング maxDataCenterId -1L = ^(-1L << dataCenterIdBits); 
 
    / ** 配列表すメジアンIDが* / 
    プライベート 最終 ロング sequenceBits = 12L ; 
 
    / ** 左にマシンID 12 * / 
    プライベート ファイナル 長い workerIdShift = sequenceBits; 
 
    / ** 17によって左(12 + 5)にIDを識別するデータ* / 
    プライベート 最終 長い dataCenterIdShift + = sequenceBits ; workerIdBits 
 
    / ** 左22を切断する時間(5 + 5 + 12)* / 
    プライベート 最終 ロング timestampLeftShift workerIdBits + + = sequenceBitsdataCenterIdBits; 
 
    / ** マスクシーケンスを生成し、ここでは4095(0b111111111111 = 0xFFF = 4095)* / 
    プライベート 最終 ロング sequenceMask -1L = ^(-1L << sequenceBits); 
 
    / ** 作業機械のID(0〜31)* / 
    プライベート ロングworkerId; 
 
    / ** データセンターID(〜31が0である)* / 
    プライベート ロングdataCenterId; 
 
    / **は、シーケンス(0〜4095)ミリ秒* / 
    プライベート ロングシーケンス= 0Lを; 
 
    / ** 最後のIDが生成されますカットオフ時間* / 
    プライベート ロング LastTimestamp = -1L ; 
 
    プライベート 静的SnowflakeIdWorker idWorker。
 
    静的{ 
        idWorker = 新しいSnowflakeIdWorker(getWorkId()、getDataCenterId())。
    } 
 
    // ==============================コンストラクタ================ ===================== 
    / ** 
     *构造函数
     * @param workerId工作ID(0〜31)
     * @param dataCenterId数据中心ID(0〜31)
      * / 
    公共 SnowflakeIdWorker(長い workerId、長いdataCenterId){
         場合(workerId> maxWorkerId || workerId <0 ){
             スロー 新しいですIllegalArgumentException(String.Formatの( "workerIdは%D未満または0より大きくすることはできません" 、maxWorkerId))。
        } 
        であれば(dataCenterId> maxDataCenterId || dataCenterId <0 ){
             スロー 新しいはIllegalArgumentException(String.Formatの( "dataCenterIdは%D未満または0より大きくすることはできません" 、maxDataCenterIdを)); 
        } 
        この .workerId = workerId。
        この .dataCenterId = dataCenterId。
    } 
 
    / ** 
     *获得下一个ID(该方法是线程安全的)
     * @return SnowflakeId
      * / 
    公共の 同期 長いですNEXTID(){
         ロングタイムスタンプ= TIMEGEN(); 
 
        // 現在の時刻を通ってスローされるべきシステムクロックバックオフ時間を示す、最後の世代のIDのタイムスタンプよりも小さい場合
        IF(タイムスタンプ< LastTimestamp){
             スロー 新しい新規のRuntimeException(
                    文字列。フォーマットは、(「クロックは、%Dミリ秒を生成することを拒否するための下位IDを動かし。」、LastTimestamp - タイムスタンプ)); 
        } 
 
        // それが同時に発生した場合、配列はミリ秒以内に行われる
        IF(LastTimestamp == タイムスタンプ){ 
            シーケンス =(配列1 +)&sequenceMask;
             // ミリ秒シーケンスオーバーフロー
            IF(配列== 0 ){
                // 次ミリ秒ブロッキング、新しいタイムスタンプ取得 
                スタンプ= tilNextMillis(LastTimestampを); 
            } 
        } 
        // タイムスタンプがミリ秒リセットシーケンスを変更する
        { 
            シーケンス = 0L ; 
        } 
 
        // 前回生成されたIDの断面 
        LastTimestamp = タイムスタンプ; 
 
        // 戦いと論理和へのシフトが一緒になって、64ビットのID形式
        リターン((タイムスタンプ- twepoch)<< timestampLeftShift)
                 |(dataCenterId << dataCenterIdShift)を
                (workerId << | workerIdShift)
                 | 配列; 
    } 
 
    / * *
     * 阻塞到下一个毫秒,直到获得新的时间戳
     * @Param LastTimestamp時間が以前に生成されたIDをカット
     * @return 現在のタイムスタンプ
      * / 
    保護 ロング tilNextMillis(ロングLastTimestamp){
         ロングタイムスタンプ= TIMEGEN();
         一方、(タイムスタンプ<= LastTimestamp){ 
            タイムスタンプ = TIMEGEN(); 
        } 
        戻りタイムスタンプは; 
    } 
 
    / ** 
     *ミリ秒で現在の時刻を返す
     * @return 現在の時間(ミリ秒)
      * / 
    保護 ロングTIMEGEN(){
         戻りのSystem.currentTimeMillisを();
    } 
 
    プライベート 静的ロングgetWorkId(){
         試み{ 
            文字列HostAddressは = Inet4Address.getLocalHost()はgetHostAddress();.
             のInt [] = INTS StringUtils.toCodePoints(HostAddressは);
             INT合計= 0 ;
             のためのint型B:INTS){ 
                合計 + = B; 
            } 
            リターンロング)(32%の合計); 
        } キャッチ(UnknownHostExceptionがE){
             // 取得に失敗した場合、バックアップは、乱数使用
            リターン RandomUtils.nextLong(0,31に); 
        }
    } 
 
    プライベート 静的ロングgetDataCenterId(){
         int型 []のint = StringUtils.toCodePoints(SystemUtils.getHostName())。
        int型の合計= 0 ;
        以下のためにint型{:int値i)を
            合計 + = I。
        } 
        リターンロング)(合計%32 )。
    } 
 
 
    / ** 
     *静态工具类
     * 
     * @return 
     * / 
    パブリック 静的ロングgenerateId(){
         長い ID = idWorker.nextId()。
        戻り値のID。 
    } 
 
    // ==============================テスト=============== ============================== 
    / ** 测试* / 
    パブリック 静的 ボイドメイン(文字列[]引数){ 
        のSystem.out .println(のSystem.currentTimeMillis())。
        長いのstartTime = System.nanoTimeの()。
        以下のためにint型 i = 0; I <50000; iは++ ){
             長い ID = SnowflakeIdWorker.generateId()。
            System.out.println(ID)。
        } 
        のSystem.out.println((System.nanoTimeの() -startTime)/ 1000000 + "MS" )。
    } 
}

 

 

おすすめ

転載: www.cnblogs.com/oldzhang1222/p/11078514.html