雪花算法詳解及源碼分析

雪花算法的簡介:

雪花算法用來實現全局唯一ID的業務主鍵,解決分庫分表之后主鍵的唯一性問題,所以就單從全局唯一性來說,其實有很多的解決方法,比如說UUID、數據庫的全局表的自增ID

但是在實際的開發過程中,我們的id除了唯一性以外,還需要去滿足有序遞增,高性能,高可用,以及需要時間戳等這樣一些特征,而雪花算法就是一個比較符合這個一類特征的全局唯一算法。

雪花算法結構的詳解:

它是一個通過64個bit位 組成的一個long類型的數字,可以將它分為四個部分,根據這四個部分的規則,生成對應的bit位的一個數據,然后組裝在一起,形成一個全局的唯一id。

第一部分:是一個bit:這個是正負號,正常情況下為零,通常無意義

1)不用 1bit:是不用的

因為二進制里第一個bit位如果是1,那么都是復數,但是我們生成的id都是正數,所以第一個bit統一都是0

第二部分:是41個bit:表示的是時間戳

2)時間戳 41bit:表示的是時間戳,單位是毫秒

41bit表示的數字多達2^41-1,也就是可以標識2^41-1個毫秒值,換算成年表示就是69年的時間。

第三、四部分:是5+5個bit:表示的是機房id以及機器id、

3)+4)工作機器Id 10bit:記錄工作機器的id,表示的是這個服務最多可以部署在2^10臺機器上,也就是1024臺機器。

但是10bit里5個bit代表機房id,5個bit代表機器id。意思就是最多代表2^個機房(32個機房),每個機房可以代表2^5和機器(32臺機器),也可以根據實際情況確定

第五部分:是12個bit:表示的序號,就是某個機房中某個機器上這一毫秒內同時生成的id的序號,0000 0000 0000

12bit可以代表的最大正整數是2^12-1=4096,也就是說可以用這個12bit代表的數字來區分同一個毫秒內的4096個不同的id。

源碼:

public class SnowFlakeUtil01 {// 起始時間戳 (可以自定義)private final long twepoch = 1288834974657L;// 機器ID所占的位數private final long workerIdBits = 5L;// 數據中心ID所占的位數private final long datacenterIdBits = 5L;// 支持的最大機器ID,結果是31 (這個移位算法可以計算最大值:-1L ^ (-1L << workerIdBits))private final long maxWorkerId = -1L ^ (-1L << workerIdBits);// 支持的最大數據中心ID,結果是31private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);// 序列在ID中占的位數private final long sequenceBits = 12L;// 機器ID左移位數private final long workerIdShift = sequenceBits;// 數據中心ID左移位數private final long datacenterIdShift = sequenceBits + workerIdBits;// 時間戳左移位數private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;// 生成序列的掩碼,這里為4095 (0b111111111111=0xfff=4095)private final long sequenceMask = -1L ^ (-1L << sequenceBits);// 工作機器ID(0~31)private long workerId;// 數據中心ID(0~31)private long datacenterId;// 毫秒內序列(0~4095)private long sequence = 0L;// 上次生成ID的時間戳private long lastTimestamp = -1L;// 構造函數public SnowFlakeUtil01(long workerId, long datacenterId) {// 檢查workerId是否在合法范圍內if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}// 檢查datacenterId是否在合法范圍內if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}/*** 獲得下一個ID (該方法是線程安全的)* @return SnowflakeId*/public synchronized long nextId() {long timestamp = timeGen();// 如果當前時間小于上一次ID生成的時間戳,說明系統時鐘回退過這個時候應當拋出異常if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}// 如果是同一時間生成的,則進行毫秒內序列if (lastTimestamp == timestamp) {// 如果毫秒相同,則從0遞增生成序列號sequence = (sequence + 1) & sequenceMask;// 毫秒內序列溢出if (sequence == 0) {// 阻塞到下一個毫秒,獲得新的時間戳timestamp = tilNextMillis(lastTimestamp);}}// 時間戳改變,毫秒內序列重置else {sequence = 0L;}// 上次生成ID的時間戳lastTimestamp = timestamp;// 移位并通過或運算拼到一起組成64位的IDreturn ((timestamp - twepoch) << timestampLeftShift) // 時間戳部分| (datacenterId << datacenterIdShift)       // 數據中心部分| (workerId << workerIdShift)               // 機器ID部分| sequence;                                 // 序列號部分}// 阻塞到下一個毫秒,直到獲得新的時間戳protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}// 返回當前時間,以毫秒為單位protected long timeGen() {return System.currentTimeMillis();}//    public static void main(String[] args) {
//        SnowFlakeUtil snowFlakeUtil = new SnowFlakeUtil(0, 0);
//        for (int i = 0; i < 100; i++) {
//            long id = snowFlakeUtil.nextId();
//            System.out.println(id);
//        }
//    }
}

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

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

相關文章

離散點云擬合三維平面參數推導(基于最小二乘)

1、背景介紹 實際中&#xff0c;很多人工構造物是由平面結構構造而成&#xff0c;如下圖所示&#xff0c;為一典型的由多個平面組成的人工構筑物。因此&#xff0c;根據離散點擬合成平面&#xff0c;獲取擬合平面方程&#xff0c;是點云數據處理中非常常見的數據處理操作。 2、…

鴻蒙Ability Kit(程序框架服務)【ExtensionAbility組件】

ExtensionAbility組件 ExtensionAbility組件是基于特定場景&#xff08;例如服務卡片、輸入法等&#xff09;提供的應用組件&#xff0c;以便滿足更多的使用場景。 每一個具體場景對應一個[ExtensionAbilityType]&#xff0c;開發者只能使用&#xff08;包括實現和訪問&#…

WPS的excel表格設置了編輯權限,要怎么取消?

在日常生活和工作中&#xff0c;我們經常會使用WPS Office辦公軟件來處理各種文檔&#xff0c;其中WPS Excel表格是我們進行數據處理和分析的重要工具。為了保護表格中的數據不被隨意修改&#xff0c;我們有時會設置編輯權限。然而&#xff0c;隨著時間的推移或需求的變更&…

基于FPGA的SystemVerilog練習

文章目錄 一、認識SystemVerilogSystemVerilog的語言特性SystemVerilog的應用領域SystemVerilog的優勢SystemVerilog的未來發展方向 二、流水燈代碼流水燈部分testbench仿真文件 三、用systemVerilog實現超聲波測距計時器測距部分led部分數碼管部分采樣部分頂層文件引腳綁定效果…

魯教版七年級數學下冊-筆記

文章目錄 第七章 二元一次方程組1 二元一次方程組2 解二元一次方程組3 二元一次方程組的應用4 二元一次方程與一次函數5 三元一次方程組 第八章 平行線的有關證明1 定義與命題2 證明的必要性3 基本事實與定理4 平行線的判定定理5 平行限的性質定理6 三角形內角和定理 第九章 概…

dpdk uio整體分析及網卡加載

參考:https://zhuanlan.zhihu.com/p/477600165 一、Linux內核知識點 1. __attribute__ constructor/destructor (1)若函數被設定為constructor屬性,則該函數會在 main()函數執行之前被自動的執行。 (2)若函數被設定為destructor屬性,則該函數會在main()函數執…

開發和滲透偷懶利器utools

目錄 1.前言 1.1 工具簡介 1.2 核心特性 1.3 使用場景 1.4 安裝與使用 1.4.1 下載&#xff1a; 1.4.2 安裝&#xff1a; 1.4.3 配置&#xff1a; 1.4.4 插件市場&#xff1a; 2.懶狗插件介紹 基本介紹 2.1 數據模擬 2.2 隨機生成虛假數據 2.3 API市場 2.4 Hoppscot…

【十二】圖解mybatis日志模塊之設計模式

圖解mybatis日志模塊之設計模式 概述 最近經常在思考研發工程師初、中、高級工程師以及系統架構師各個級別的工程師有什么區別&#xff0c;隨著年齡增加我們的技術級別也在提升&#xff0c;但是很多人到了高級別反而更加憂慮&#xff0c;因為it行業35歲年齡是個坎這是行業里的共…

一文讀懂數據庫中的DB、DBMS、DBS、DBAS

目前數據庫的應用非常廣泛,幾乎各行各業都在直接或間接地與數據庫打交道,例如網上購物、銀行業務、鐵路購票和酒店住宿等。在實際應用中,數據庫、數據庫管理系統、數據庫系統和數據庫應用系統經常被統稱為數據庫,而實質上這4個概念是不一樣的,它們具有不同的定義和含義。下…

暴力數據結構之排序大雜燴

1. 冒泡排序&#xff1a;O(N^2) 邏輯解析&#xff1a; 冒泡排序并沒有什么實際意義&#xff0c;但是有教學意義&#xff0c;相信大部分小白在學習的初期第一個接觸的排序就是冒泡排序。那么接下來我們了解一下他的底層邏輯&#xff1a; 冒泡排序顧名思義就是將最大&#xff08…

PID——調參的步驟

第一步&#xff1a;確定比例增益P 確定比例增益 P 時&#xff0c;首先去掉 PID 的積分項和微分項&#xff0c;一般是令 Ti0、 Td0&#xff08;具體見PID 的參數設定說明&#xff09;&#xff0c;使PID 為純比例調節。 輸入設定為系統允許的最大值60%~70%&#xff0c;由0逐漸加…

idea項目maven下載依賴報錯

報錯&#xff1a; 1、Failure to find bad.robot:simple-excel:jar:1.0 in https://maven.aliyun.com/repository/public was cached in the local repository, resolution will not be reattempted until the update interval of aliyunmaven has elapsed or updates are forc…

python的while循環與for循環總結

前兩章中&#xff0c;我們跟著海綿寶寶的故事&#xff0c;掌握了 while 循環和 for 循環&#xff0c;這兩種不同的循環模式。while 循環和 for 循環都需要有 循環體 和 縮進&#xff0c;我們來復習一下它倆的語法規則&#xff1a; while 循環與 for 循環辨析 學到這里&#x…

Microsoft Edge TTS引擎實現文字轉語音小工具

Microsoft Edge TTS引擎實現文字轉語音小工具 ? 看了一篇文章關于使用Microsoft Edge TTS引擎進行文本轉語音的介紹。正好單位工作上經常用到音視頻的制作和轉換。但是文字變成音頻一直都是播音員口播實現。現在到了AI時代,各種功能強大的AI大模型已經應用到各個領域,大大提…

Docker鏡像導入導出

Docker鏡像導入導出 相關命令 docker export 容器id > x:/xx/xx.tar ##導出容器快照 docker import - x:/xx/xx.tar ##導入容器快照 docker save 鏡像id > x:/xx/xx.tar ##導出鏡像 docker load < x:/xx/xx.tar ##導入鏡像命令詳解 docker save …

在鯤鵬服務器搭建k8s高可用集群分享

高可用架構 本文采用kubeadm方式搭建k8s高可用集群&#xff0c;k8s高可用集群主要是對apiserver、etcd、controller-manager、scheduler做的高可用&#xff1b;高可用形式只要是為&#xff1a; 1. apiserver利用haproxykeepalived做的負載&#xff0c;多apiserver節點同時工作…

nginx反向代理了解

文章目錄 Nginx反向代理反向代理系統調優Proxy Buffer相關指令 Nginx 具有高性能的http和反向代理的web服務器&#xff0c;同時也是一個pop3/smtp/imap代理服務器&#xff0c;使用c語言編寫 **Web服務器&#xff1a;**也叫網頁服務器&#xff0c;web server&#xff0c;主要功…

易聯眾智慧云膠片平臺,助推醫學影像服務“向云端”

在門診室里,張女士焦急地告訴主治醫師,自己忘了帶CT膠片。“您別急,我用系統查詢一下。”醫生輕點幾下鼠標進入云膠片平臺,只用不到10秒就順利完成了影像調取。“不僅我可以看到,您在手機上也能隨時隨地查閱。”張女士根據提示操作,不僅能調閱自己的影像檔案,連抽血化驗結果都可…

Spring MVC 啟動流程?

在 web.xml 文件中給 Spring MVC 的 Servlet 配置了 load-on-startup&#xff0c;所以程序啟動的時候會初始化 Spring MVC&#xff0c;在 HttpServletBean 中將配置的 contextConfigLocation屬性設置到 Servlet 中&#xff0c;然后在FrameworkServlet 中創建了 WebApplicationC…

[GeoServer系列]Shapefile數據發布

【GeoServer系列】——安裝與發布shapefile數據-CSDN博客 將待發布數據放置指定目錄下 webapps\geoserver\data\data 創建存儲倉庫 新建矢量數據源 發布圖層 設置邊框 設置樣式 使用 方式1 let highRoad new Cesium.WebMapServiceImageryProvider({url: http://local…