理解分布式id生成算法--雪花算法(SnowFlake)
分布式ID生成算法的有很多種,Twitter的SnowFlake就是其中經(jīng)典的一種。
注:
1B就是1個(gè)字節(jié)。
Byte、KB、B、MB、GB之間的關(guān)系是:
Bit——比特 ; B ——字節(jié);KB——千字節(jié);MB——兆字節(jié);GB——吉字節(jié);TB——太字節(jié)
1bit=0.125b?;1B=8 Bit? ?;1KB=1024B? ? ? 1MB=1024KB;1GB=1024MB;1TB=1024GB
?
1位,不用。二進(jìn)制中最高位為1的都是負(fù)數(shù),但是我們生成的ID一般都使用整數(shù),所以這個(gè)最高位固定是0.
41位,用來(lái)記錄時(shí)間戳(毫秒)
? ? ? ? ? ? 41位可以表示正整數(shù)(計(jì)算機(jī)中整數(shù)包含0),可以表示的數(shù)值范圍是:0至$2^{41}-1$,
? ? ? ? ? ? 減1是因?yàn)榭杀硎镜牡臄?shù)值范圍是從0開(kāi)始算的,而不是1.
? ? ? ? ? ? ?也就是說(shuō)41位可以表示$2^{41}-1$個(gè)毫秒的值,轉(zhuǎn)化成單位年則是$2^({41}-1)/(1000*60*60*24*365)=69$年
10位,用來(lái)記錄工作機(jī)器ID。
? ? ? ? ?可以部署在$2^{10}=1024$個(gè)字節(jié)。包括5位datacenterId和5位workerId。
? ? ? ? ? 5位(bit)可以表示的最大正整數(shù)是$2^{5}-1=31$,即可以用0,1,2,3....31這32個(gè)數(shù)字,來(lái)表示不同的datacenterId?
? ? ? ? ? 或者workerId.
12位,序列號(hào),用來(lái)記錄同毫秒內(nèi)產(chǎn)生的不同Id。
? ? ? ? 12位(bit)可以表示的最大整數(shù)是$2^{12}-1=4095$,即可以用0、1、2、3....4094這4095個(gè)數(shù)字,來(lái)表示同一機(jī)器
? ? ? ? ?同一時(shí)間戳(毫秒)內(nèi)產(chǎn)生的4095個(gè)ID序號(hào)。
由于在java中64bit的整數(shù)是long類型,所以在java中SnowFlake算法生產(chǎn)的ID就是longKauai存儲(chǔ)的,
?
SnowFlake可以保證:
所有生成ID按時(shí)間趨勢(shì)遞增。
整個(gè)分布式系統(tǒng)內(nèi)不會(huì)產(chǎn)生重復(fù)ID(因?yàn)閐atacenterID和wokerID來(lái)做區(qū)分)
?
?
java代碼工具類:
?
package suanfa;
/**
* ### 雪花算法:
SnowFlake算法用來(lái)生成64位的ID,剛好可以用long整型存儲(chǔ),能夠用于分布式系統(tǒng)中生產(chǎn)唯一的ID, 并且生成的ID有大致的順序。 在這次實(shí)現(xiàn)中,生成的64位ID可以分成5個(gè)部分:
`0 - 41位時(shí)間戳 - 5位數(shù)據(jù)中心標(biāo)識(shí) - 5位機(jī)器標(biāo)識(shí) - 12位序列號(hào)`
````java
* twitter的snowflake算法 -- java實(shí)現(xiàn)
*
* @author beyond
* @date 2016/11/26
*/
public class SnowFlake {
/**
* 起始的時(shí)間戳
*/
private final static long START_STMP = 1480166465631L;
/**
* 每一部分占用的位數(shù)
*/
private final static long SEQUENCE_BIT = 12; //序列號(hào)占用的位數(shù)
private final static long MACHINE_BIT = 5; //機(jī)器標(biāo)識(shí)占用的位數(shù)
private final static long DATACENTER_BIT = 5;//數(shù)據(jù)中心占用的位數(shù)
/**
* 每一部分的最大值
*/
//最大支持?jǐn)?shù)據(jù)中心節(jié)點(diǎn)數(shù)0~31,一共32個(gè)
private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
//最大支持機(jī)器節(jié)點(diǎn)數(shù)0~31,一共32個(gè)
private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
//序列號(hào)0~12,一共12個(gè)
private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
/**
* 每一部分向左的位移
*/
//機(jī)器節(jié)點(diǎn)左移12位
private final static long MACHINE_LEFT = SEQUENCE_BIT;
//數(shù)據(jù)中心節(jié)點(diǎn)左移17位
private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
//時(shí)間毫秒數(shù)左移22位
private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
private long datacenterId; //數(shù)據(jù)中心
private long machineId; //機(jī)器標(biāo)識(shí)
private long sequence = 0L; //序列號(hào)
private long lastStmp = -1L;//上一次時(shí)間戳 //最大為4095
public SnowFlake(long datacenterId, long machineId) {
if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
}
if (machineId > MAX_MACHINE_NUM || machineId < 0) {
throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
}
this.datacenterId = datacenterId;
this.machineId = machineId;
}
/**
* 產(chǎn)生下一個(gè)ID
*
* @return
*/
public synchronized long nextId() {
long currStmp = getNewstmp();
if (currStmp < lastStmp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (currStmp == lastStmp) {
//相同毫秒內(nèi),序列號(hào)自增
sequence = (sequence + 1) & MAX_SEQUENCE;
//同一毫秒的序列數(shù)已經(jīng)達(dá)到最大
if (sequence == 0L) {
currStmp = getNextMill();
}
} else {
//不同毫秒內(nèi),序列號(hào)置為0
sequence = 0L;
}
lastStmp = currStmp;
return (currStmp - START_STMP) << TIMESTMP_LEFT //時(shí)間戳部分
| datacenterId << DATACENTER_LEFT //數(shù)據(jù)中心部分
| machineId << MACHINE_LEFT //機(jī)器標(biāo)識(shí)部分
| sequence; //序列號(hào)部分
}
private long getNextMill() {
long mill = getNewstmp();
while (mill <= lastStmp) {
mill = getNewstmp();
}
return mill;
}
private long getNewstmp() {
return System.currentTimeMillis();
}
public static void main(String[] args) {
//數(shù)據(jù)中心id,機(jī)器標(biāo)識(shí)id
SnowFlake snowFlake = new SnowFlake(2, 3);
System.out.println(snowFlake.nextId());
}
}
?
轉(zhuǎn)載于:https://www.cnblogs.com/javaDB2019/p/10935854.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的理解分布式id生成算法--雪花算法(SnowFlake)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2.6.24及以上版本内核裁剪后启动黑屏
- 下一篇: Oracle 11g 新特性 -- 自动