日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

雪花算法

SnowFlake 算法,是 Twitter 開源的分布式 id 生成算法。其核心思想就是:使用一個 64 bit 的 long 型的數(shù)字作為全局唯一 id。在分布式系統(tǒng)中的應用十分廣泛,且ID 引入了時間戳,基本上保持自增的。本文主要是是實現(xiàn)了單機版本的算法,使用多臺計算機構成分布式的ID生成服務也是可以的,預留了相關的方法參數(shù)。

應用范圍

1、在jdk中自帶的uuid算法可以來生成唯一性的32位字符串【拼接上‘-’之后,是36位,如:’
4211210a-ba56-41b4-b055-6262411970a4’】,uuid算法得到的id是無序的,而且是字符串,數(shù)據表記錄多時,查詢效率不高

2、基于數(shù)據庫的sequnce【通過表也可以模擬sequence】來生成,在分布式系統(tǒng)中更新記錄不方便,只能操作主表的更新。

3、雪花算法在分布式系統(tǒng)中可以較好地使用。

原理

把64位進行拆分,分為如下幾個部份

第1部份只占1位,而且必需為0,因為最高位0表示正數(shù)。

第2部份是時間戳,占41位【為什么是41位,后面會介紹】,最多可以表示2^41,大約是69年

第3部份是產生的機器號,占10位【也可以是其它位數(shù),不一定非得是10位,官方約定是10位】,最多可以表示2^10,相當于1024臺機器,這部分可以劃成兩個維度,如下:

3.1 拿5位出來做為機房號,最多可以表示 2^5個機房號,也就是最多32個機房編號

3.2 拿5位出來做為機器號,最多可以表示 2^5臺電腦,也就是最多32臺電腦編號

第4部份是時間戳,占12位,相當于在同一個毫秒內,可以最大支持2^12,也就是4096個序號【普通的計算機根本達不到】

代碼實現(xiàn)

 

public class IdGenerator {

 

//定義屬性 [機器碼10位,如何分配成 機房碼和電腦碼,做為屬性,這里默認都是5]

private final long dataCenterBits = 5L; //機房碼的位數(shù)

private final long computerBits = 5L; //電腦碼的位數(shù)

//最后的序列碼,默認從0開始

private long sequence = 0L;

//記錄執(zhí)行的最后時間,以毫秒為單位,默認初始化為-1L

private long lastTimeStamp = -1L;

 

//因為要做二進制運算,我們需要定義如下屬性來記錄每個部份所在的位置的偏移量

private final long sequenceBits = 12; //序號占用12位

private final long computerIdShift = sequenceBits; //電腦碼的偏移量

private final long dataCenterIdShift = computerIdShift + computerBits; //機房碼的偏移量

private final long timeStampShift = dataCenterIdShift + dataCenterBits; //時間戳的偏移量

 

//根據機房碼的位數(shù),來計算出機房碼最大值

private final long MAX_DATA_CENTER = -1L ^ (-1L << dataCenterBits); //相當于 11111, 也就是 31

private final long MAX_COMPUTER = -1L ^ (-1L << computerBits); //同上

private final long SEQUENCE_MASK = -1L ^ (-1L << sequenceBits); // 為防止序列號溢出而準備的掩碼,相當于 11111111 111

 

//定義屬性

private long computerId; //電腦的id 【在分布式系統(tǒng)中,記錄這個雪花號是由哪一臺電腦生成的】

private long dataCenterId; //機房的id 【在分布式系統(tǒng)中,記錄這個雪花號是由哪一個中心機房里的電腦生成的】

//構造

public IdGenerator(long computerId, long dataCenterId) {

//對參數(shù)的有效性進行判斷,由于機房碼和電腦碼都是5位,所以,它們的值最大都不能超過31

if(computerId > MAX_COMPUTER || computerId < 0) {

throw new IllegalArgumentException(String.format("電腦編號不能大于 %d 或者小于 %d n",MAX_COMPUTER,0));

}

if(dataCenterId > MAX_DATA_CENTER || dataCenterId < 0) {

throw new IllegalArgumentException(String.format("機房編號不能大于 %d 或者小于 %dn",MAX_DATA_CENTER, 0));

}

//賦值

this.computerId = computerId;

this.dataCenterId = dataCenterId;

}

/***************

* 核心方法,利用雪花算法來獲取一個唯一性的ID

* @return

*/

public synchronized long nextId() {

//1.獲取當前的系統(tǒng)時間

long currTime = getCurrentTime();

//2. 判斷是否在同一個時間內的請求

if(currTime == lastTimeStamp) {

//2.1 sequence 要增1, 但要預防sequence超過 最大值4095,所以要 與 SEQUENCE_MASK 按位求與

sequence = (sequence + 1) & SEQUENCE_MASK;

//2.2 進一步判斷,如果在同一個毫秒內,sequence達到了4096【1 0000 0000 0000】,則lastTime時間戳必需跳入下一個時間,因為同一個毫秒內

//sequence只能產生4096個【0-4095】,當超過時,必需跳入下一個毫秒

// 【此情況極少出現(xiàn),但不可不防,這意味著1個毫秒內,JVM要執(zhí)行此方法達到4096次,我這個電腦執(zhí)行遠達不到。】

if(sequence == 0) {

currTime = unitNextTime();

}

} else {

//如果不是與lastTime一樣,則表示進入了下一個毫秒,則sequence重新計數(shù)

sequence = 0L;

}

//3. 把當前時間賦值給 lastTime, 以便下一次判斷是否處在同一個毫秒內

lastTimeStamp = currTime;

//4. 依次把各個部門求出來并通過邏輯或 拼接起來

return (this.lastTimeStamp << timeStampShift) | //把當前系統(tǒng)時間 左移22位

(this.dataCenterId << dataCenterIdShift) | //把機房編號 左移17位

(this.computerId << computerIdShift) | //把計算機號編號左移 12位

this.sequence; //最后的序列號占12位,無需移動

}

 

/******

* 等待毫秒數(shù)進入下一個時間

* @return

*/

private long unitNextTime() {

//1.再次獲取系統(tǒng)時間

long timestamp = getCurrentTime();

//2. 判斷 lastTime與currentTime是否一樣

while(timestamp <= lastTimeStamp) {

//2.1 繼續(xù)獲取系統(tǒng)時間,直到上面的條件不成立為止

timestamp = getCurrentTime();

}

//3. 返回

return timestamp;

}

 

/*****

* 用來獲取當前的系統(tǒng)時間,以毫秒為單位

* @return

*/

private long getCurrentTime() {

return System.currentTimeMillis();

}

}

 

測試類

 

public class UseIdGenerator {

/****

* 主方法

* @param args

*/

public static void main(String[] args) {

//這里兩個參數(shù)都是1,表示1號機房和1號電腦【在分布式系統(tǒng)中,每個電腦知道自己所在的機房和編號】

IdGenerator ig = new IdGenerator(1,1);

//循環(huán)生成

long result = -1;

for(int i = 0;i<100000;i++) {

result = ig.nextId();

System.out.println(result+" , "+Long.toBinaryString(result));

}

}

 

}

分享到:
標簽:算法 雪花
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定