理解分布式id生成算法--雪花算法(SnowFlake)

分布式ID生成算法的有很多種,Twitter的SnowFlake就是其中經典的一種。

注:

1B就是1個字節。
Byte、KB、B、MB、GB之間的關系是:
Bit——比特 ; B ——字節;KB——千字節;MB——兆字節;GB——吉字節;TB——太字節
1bit=0.125b?;1B=8 Bit? ?;1KB=1024B? ? ? 1MB=1024KB;1GB=1024MB;1TB=1024GB

?

1位,不用。二進制中最高位為1的都是負數,但是我們生成的ID一般都使用整數,所以這個最高位固定是0.

41位,用來記錄時間戳(毫秒)

? ? ? ? ? ? 41位可以表示正整數(計算機中整數包含0),可以表示的數值范圍是:0至$2^{41}-1$,

? ? ? ? ? ? 減1是因為可表示的的數值范圍是從0開始算的,而不是1.

? ? ? ? ? ? ?也就是說41位可以表示$2^{41}-1$個毫秒的值,轉化成單位年則是$2^({41}-1)/(1000*60*60*24*365)=69$年

10位,用來記錄工作機器ID。

? ? ? ? ?可以部署在$2^{10}=1024$個字節。包括5位datacenterId和5位workerId。

? ? ? ? ? 5位(bit)可以表示的最大正整數是$2^{5}-1=31$,即可以用0,1,2,3....31這32個數字,來表示不同的datacenterId?

? ? ? ? ? 或者workerId.

12位,序列號,用來記錄同毫秒內產生的不同Id。

? ? ? ? 12位(bit)可以表示的最大整數是$2^{12}-1=4095$,即可以用0、1、2、3....4094這4095個數字,來表示同一機器

? ? ? ? ?同一時間戳(毫秒)內產生的4095個ID序號。

由于在java中64bit的整數是long類型,所以在java中SnowFlake算法生產的ID就是longKauai存儲的,

?

SnowFlake可以保證:

所有生成ID按時間趨勢遞增。

整個分布式系統內不會產生重復ID(因為datacenterID和wokerID來做區分)

?

?

java代碼工具類:

?

package suanfa;

/**
* ### 雪花算法:
SnowFlake算法用來生成64位的ID,剛好可以用long整型存儲,能夠用于分布式系統中生產唯一的ID, 并且生成的ID有大致的順序。 在這次實現中,生成的64位ID可以分成5個部分:

`0 - 41位時間戳 - 5位數據中心標識 - 5位機器標識 - 12位序列號`

````java
* twitter的snowflake算法 -- java實現
*
* @author beyond
* @date 2016/11/26
*/
public class SnowFlake {

/**
* 起始的時間戳
*/
private final static long START_STMP = 1480166465631L;

/**
* 每一部分占用的位數
*/
private final static long SEQUENCE_BIT = 12; //序列號占用的位數
private final static long MACHINE_BIT = 5; //機器標識占用的位數
private final static long DATACENTER_BIT = 5;//數據中心占用的位數

/**
* 每一部分的最大值
*/
//最大支持數據中心節點數0~31,一共32個
private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
//最大支持機器節點數0~31,一共32個
private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
//序列號0~12,一共12個
private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);

/**
* 每一部分向左的位移
*/
//機器節點左移12位
private final static long MACHINE_LEFT = SEQUENCE_BIT;
//數據中心節點左移17位
private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
//時間毫秒數左移22位
private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;

private long datacenterId; //數據中心
private long machineId; //機器標識
private long sequence = 0L; //序列號
private long lastStmp = -1L;//上一次時間戳 //最大為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;
}

/**
* 產生下一個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) {
//相同毫秒內,序列號自增
sequence = (sequence + 1) & MAX_SEQUENCE;
//同一毫秒的序列數已經達到最大
if (sequence == 0L) {
currStmp = getNextMill();
}
} else {
//不同毫秒內,序列號置為0
sequence = 0L;
}

lastStmp = currStmp;

return (currStmp - START_STMP) << TIMESTMP_LEFT //時間戳部分
| datacenterId << DATACENTER_LEFT //數據中心部分
| machineId << MACHINE_LEFT //機器標識部分
| sequence; //序列號部分
}

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) {
//數據中心id,機器標識id
SnowFlake snowFlake = new SnowFlake(2, 3);
System.out.println(snowFlake.nextId());

}

}

?

轉載于:https://www.cnblogs.com/javaDB2019/p/10935854.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/448846.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448846.shtml
英文地址,請注明出處:http://en.pswp.cn/news/448846.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[ZJOI2010]貪吃的老鼠

P2570 [ZJOI2010]貪吃的老鼠 在Ta的博客查看 顯然二分&#xff0c;最大流判定 要滿足兩個條件&#xff1a; (1) 在任一時刻&#xff0c;一只老鼠最多可以吃一塊奶酪&#xff1b; (2) 在任一時刻&#xff0c;一塊奶酪最多被一只老鼠吃。 先按照奶酪的邊界進行離散化&#xff0c…

IP: 169.254.0.0/16 地址用途

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 一直困惑169.254.0.0/16是干嘛的&#xff0c;每次筆記本dhcp獲取地址失敗后&#xff0c;就會隨機在這個B類地址段獲取一個地址&#…

值得借鑒的30條好習慣

我有幸一直能生活在比較好的圈子中&#xff0c;我的優秀的同學、舍友&#xff0c;乃至我現在創業后遇到的優秀創業者&#xff0c;從他們身上看到和學到一些好的習慣。 我一直覺得&#xff0c;好的習慣&#xff0c;是成功和進步的重要一點。我隨手總結一些給大家&#xff0c;零散…

【PKUSC2019】線弦圖【計數】【樹形DP】【分治FFT】

Description 定義線圖為把無向圖的邊變成點&#xff0c;新圖中點與點之間右邊當且僅當它們對應的邊在原圖中有公共點&#xff0c;這樣得到的圖。 定義弦圖為不存在一個長度大于3的純環&#xff0c;純環的定義是在環上任取兩個不相鄰的點&#xff0c;它們之間都沒有邊&#xff0…

注解 @PostConstruct 與 @PreDestroy 詳解及實例

簡介 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Java EE5 引入了PostConstruct和PreDestroy這兩個作用于Servlet生命周期的注解&#xff0c;實現Bean初始化之前和銷毀之前的自定義操…

別讓6種不良心理偷走你的好人緣

眾所周知&#xff0c;擁有正常、健康的交際圈對于人的身心健康都是很有幫助的。但是若想維系好自己的交際圈&#xff0c;也是很不容易的&#xff0c;甚至在不經意間產生的某些心理&#xff0c;就會直接給大家的人際交往帶來影響。那么接下來&#xff0c;小編就先為大家歸納一下…

PHP 安裝xdebug

xdebug官網: https://xdebug.org 安裝步驟如下: 使用 phpinfo() 打印出PHP相關信息, 全選, 復制 打開 xdebug 網站: https://xdebug.org/wizard.php 在圖中輸入框中粘貼你復制的信息, 點擊 Analyse my phpinfo() output 在結果中點擊下載, 然后按照它提示的步驟進行操作即可…

apt-clone:備份已安裝的軟件包并在新的 Ubuntu 系統上恢復它們

當我們在基于 Ubuntu/Debian 的系統上使用 apt-clone&#xff0c;包安裝會變得更加容易。如果你需要在少量系統上安裝相同的軟件包時&#xff0c;apt-clone 會適合你。 如果你想在每個系統上手動構建和安裝必要的軟件包&#xff0c;這是一個耗時的過程。它可以通過多種方式實現…

分布式消息中間件 : Rocketmq

簡述 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 分布式消息中間件&#xff0c;主要是實現分布式系統中解耦、異步消息、流量銷鋒、日志處理等場景。生產中用的最多的消息隊…

PV、UV、UIP、VV、CPC、CPM、RPM、CTR指的是什么?

PV(PageView)&#xff1a;網站瀏覽量&#xff0c;指頁面的瀏覽次數&#xff0c;用以衡量網站用戶訪問的網頁數量。用戶沒打開一個頁面便記錄1次PV&#xff0c;多次打開同一頁面則瀏覽量累計&#xff1b;UV(UniqueVistor)&#xff1a;獨立訪客數&#xff0c;指1天內訪問某站點的…

linux opencl(AMD) Example

最近對并行計算很感興趣。不過搞MPI對我來說暫時沒什么用&#xff0c;基于GPU的并行計算倒是挺實用。網上的資料都是CUDA的。實質上我對CUDA一點興趣都沒有。無論別人的架構多么先進&#xff0c;我這個只有AMD顯卡的小孩都是旁觀者而已。在這里記錄一下一個opencl程序的編譯過程…

php使用supervisor管理進程腳本

supervisor是用python開發的一個在linux系統下的進程管理工具&#xff0c;可以方便的監聽&#xff0c;啟動&#xff0c;停止一個或多個進程。當一個進程被意外殺死后&#xff0c;supervisor監聽到后&#xff0c;會自動重新拉起進程。 一、supervisor的安裝 1、通過easy_install…

重寫規則和重載規則

重寫規則&#xff1a; 發生在有繼承關系的類之間&#xff08;同一類就是重載了&#xff09;相同的方法名&#xff0c;參數列表&#xff0c;返回類型可見性&#xff08;public,protected,private&#xff09;不能被縮小異常不能被放大規則與c中不一樣靜態類型不能被重寫方法重載…

消息中間件:RocketMQ 介紹(特性、術語、原理、優缺點、消息順序、消息重復)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 消息中間件的作用 1. 應用解耦 2. 異步處理 比如用戶注冊場景&#xff0c;注冊主流程完成以后&#xff0c;需要調用郵件系統發送郵件…

C# JsonHelper類

記錄一下&#xff0c;方便下次用。 public class JsonHelper{#region Json/// <summary>/// JavaScriptSerializer/// </summary>/// <typeparam name"T"></typeparam>/// <param name"obj"></param>/// <returns&…

[譯】Redux入門教程(一)

前言 老外寫技術文章真是叼&#xff0c;這是國外的一個程序員寫的一個簡單易懂,循序漸進的Redux教程&#xff0c;本著共享的精神&#xff0c;就翻譯出來給大家一起看&#xff0c;文章最后有鏈接&#xff0c;不想看我翻譯的直接去看原文吧。 下面是原教程的英文目錄 這篇先更三分…

使用 Intellij Idea 打包 java 工程為可執行 jar 包

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 其實還有個簡單多了方法&#xff0c;見&#xff1a; 超簡單方法&#xff1a; Intellij Idea 把 java 工程打成可運行的 jar 步驟&#x…

QuickStart系列:docker部署之Gitlab本地代碼倉庫

gitlab是可以在本地搭建的使用git作為源代碼管理的倉庫。 運行環境&#xff1a; win10vmware14docker7docker 1. 使用命令拉取鏡像&#xff08;非必須&#xff0c;耗時比較久&#xff0c;這里以ce為準&#xff0c;ce是社區版&#xff0c;ee是企業版&#xff09;&#xff1a; do…

超簡單方法: Intellij Idea 把 java 工程打成可運行的 jar

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 找到 Intellij Idea 最下面的 Terminal 選項&#xff0c;并點擊進入該界面。 2. 在光標位置輸入命令&#xff1a;mvn clean 。清理…

LDAP-輕量級目錄訪問協議(統一認證)

概念 LDAP是輕量目錄訪問協議&#xff0c;英文全稱是Lightweight Directory Access Protocol&#xff0c;一般都簡稱為LDAP。 參考資料 LDAP概念和原理介紹 我花了一個五一終于搞懂了OpenLDAP LDAP-Apache Directory Studio使用&#xff08;創建DC.OU及用戶&#xff09; 轉載于…