Java實(shí)現(xiàn)雪花算法的工具類介紹
簡介
雪花 (SnowFlake )算法是一種分布式唯一ID生成算法,可以生成全局唯一的ID標(biāo)識(shí)符,就像自然界中雪花一般沒有相同的雪花。它的核心思想是將一個(gè)64位的整數(shù)分成4部分,分別是:
- 1位標(biāo)識(shí)符:即最高位,始終為0,用于區(qū)分正數(shù)和負(fù)數(shù)。
- 41位時(shí)間戳:表示生成ID的時(shí)間戳,精確到毫秒級(jí)別,可以使用69年。
- 10位數(shù)據(jù)中心ID:表示數(shù)據(jù)中心的編號(hào),可以支持1024個(gè)數(shù)據(jù)中心。
- 12位機(jī)器ID:表示機(jī)器的編號(hào),可以支持4096臺(tái)機(jī)器。
snowflake生成的ID整體上按照時(shí)間自增排序,并且整個(gè)分布式系統(tǒng)內(nèi)不會(huì)產(chǎn)生ID碰撞(由datacenter和workerId作區(qū)分),并且效率較高。
在同一毫秒內(nèi),不同的機(jī)器或數(shù)據(jù)中心可以生成不同的序列號(hào),通過這種方式保證了生成的ID的唯一性。另外,由于時(shí)間戳占據(jù)了64位整數(shù)的高位部分,因此生成的ID是越來越大的,可以滿足一些需要按照時(shí)間順序排序的場景需求。
雪花算法的優(yōu)點(diǎn)在于:
- 簡單易實(shí)現(xiàn):主要依賴于時(shí)間戳、數(shù)據(jù)中心ID和機(jī)器ID三個(gè)參數(shù),實(shí)現(xiàn)起來比較簡單。
- 唯一性:生成的ID具有全局唯一性,可以滿足分布式系統(tǒng)的需求。
- 時(shí)間有序:生成的ID是按照時(shí)間有序遞增的,可以滿足一些需要按照時(shí)間順序排序的場景需求,存入數(shù)據(jù)庫中,索引效率高。。
- 可擴(kuò)展性:可以根據(jù)需要增加數(shù)據(jù)中心ID和機(jī)器ID的位數(shù),支持更多的數(shù)據(jù)中心和機(jī)器。
- 高性能高可用:生成時(shí)不依賴于數(shù)據(jù)庫,完全在內(nèi)存中生成。
- 容量大:每秒中能生成數(shù)百萬的自增ID。
但是,雪花算法也存在一些缺點(diǎn):
- 依賴于系統(tǒng)時(shí)鐘:如果系統(tǒng)時(shí)鐘回?fù)?,則可能會(huì)生成重復(fù)的ID。
- 數(shù)據(jù)中心ID和機(jī)器ID需要手動(dòng)分配:需要手動(dòng)配置數(shù)據(jù)中心ID和機(jī)器ID,不太方便管理。
- 機(jī)器編號(hào)有限:12位機(jī)器ID只能支持4096臺(tái)機(jī)器,如果需要支持更多的機(jī)器,則需要增加機(jī)器ID的位數(shù)。
綜上所述,雪花算法是一種簡單易實(shí)現(xiàn)、具有唯一性和時(shí)間有序性的分布式ID生成算法,適用于分布式系統(tǒng)中的唯一ID標(biāo)識(shí)符的生成。
Java實(shí)現(xiàn)
public class Snowflake { // 開始時(shí)間戳,一般為項(xiàng)目啟動(dòng)時(shí)間 private final long twepoch = 1288834974657L; // 機(jī)器ID所占的位數(shù) private final long workerIdBits = 5L; // 數(shù)據(jù)標(biāo)識(shí)ID所占的位數(shù) private final long datacenterIdBits = 5L; // 支持的最大機(jī)器ID,結(jié)果是31 private final long maxWorkerId = ~(-1L << workerIdBits); // 支持的最大數(shù)據(jù)標(biāo)識(shí)ID,結(jié)果是31 private final long maxDatacenterId = ~(-1L << datacenterIdBits); // 序列號(hào)所占的位數(shù) private final long sequenceBits = 12L; // 機(jī)器ID向左移12位 private final long workerIdShift = sequenceBits; // 數(shù)據(jù)標(biāo)識(shí)ID向左移17位(12+5) private final long datacenterIdShift = sequenceBits + workerIdBits; // 時(shí)間戳向左移22位(5+5+12) private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; // 生成序列的掩碼,這里是4095 private final long sequenceMask = ~(-1L << sequenceBits); private long workerId; // 機(jī)器ID private long datacenterId; // 數(shù)據(jù)標(biāo)識(shí)ID private long sequence = 0L; // 序列號(hào) private long lastTimestamp = -1L; // 上次生成ID的時(shí)間戳 public Snowflake(long workerId, long datacenterId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); } 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; } public synchronized long nextId() { long timestamp = timeGen(); if (timestamp < lastTimestamp) { throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } if (lastTimestamp == timestamp) { sequence = (sequence + 1) & sequenceMask; // 序列號(hào)自增 if (sequence == 0) { // 序列號(hào)超過最大值,則等待下一個(gè)時(shí)間戳 timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; // 序列號(hào)重置為0 } lastTimestamp = timestamp; return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; } private long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } private long timeGen() { return System.currentTimeMillis(); } public static void main(String[] args) { Snowflake idWorker = new Snowflake(0, 0); for (int i = 0; i < 1000; i++) { long id = idWorker.nextId(); System.out.println(Long.toBinaryString(id)); System.out.println(id); } } }
Java相關(guān)工具類
Java版Snowflake開源庫比較多,以下是一些常用的開源庫及其使用方式:
1.Twitter的snowflake:是雪花算法最早的Java實(shí)現(xiàn)版本,支持高并發(fā)、低延遲、高可用等特點(diǎn)。使用方式:
Snowflake snowflake = new Snowflake(workerId, datacenterId); long id = snowflake.nextId();
2.百度的UidGenerator:是基于Twitter的snowflake算法改進(jìn)而來的,支持高性能、高可用、高并發(fā)等特點(diǎn)。使用方式:
UidGenerator uidGenerator = UidGenerator.getUidGenerator(); long id = uidGenerator.getUID();
3.美團(tuán)的Leaf:是一款高性能、輕量級(jí)的分布式ID生成器,支持多種ID生成算法,包括Snowflake算法。使用方式:
SegmentIDGenImpl idGen = new SegmentIDGenImpl(); idGen.init(); long id = idGen.getId();
4.阿里巴巴的nacos:是一款輕量級(jí)的服務(wù)注冊(cè)與發(fā)現(xiàn)工具,其中包含了雪花算法的Java實(shí)現(xiàn)版本。使用方式:
SnowFlake snowFlake = new SnowFlake(dataCenterId, machineId); long id = snowFlake.nextId();
5.yitter
6.hutool工具類
Snowflake snowflake = IdUtil.getSnowflake(1, 1); long id = snowflake.nextId();
到此這篇關(guān)于Java實(shí)現(xiàn)雪花算法的工具類介紹的文章就介紹到這了,更多相關(guān)Java雪花算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java多線程中線程的兩種創(chuàng)建方式及比較代碼示例
這篇文章主要介紹了Java多線程中線程的兩種創(chuàng)建方式及比較代碼示例,簡單介紹了線程的概念,并行與并發(fā)等,然后通過實(shí)例代碼向大家展示了線程的創(chuàng)建,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11Spring?Boot中獲取request的三種方式及請(qǐng)求過程
這篇文章主要介紹了Spring?Boot當(dāng)中獲取request的三種方式,包括請(qǐng)求過程流程分析及response常用API,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03Java源碼解析HashMap的tableSizeFor函數(shù)
今天小編就為大家分享一篇關(guān)于Java源碼解析HashMap的tableSizeFor函數(shù),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-01-01聊聊springboot靜態(tài)資源加載的規(guī)則
這篇文章主要介紹了springboot靜態(tài)資源加載的規(guī)則,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Spring?中使用?Validation?注解校驗(yàn)參數(shù)的方法
本文介紹了如何在Spring中使用Validation注解進(jìn)行參數(shù)校驗(yàn),包括引入依賴、簡單示例、常見校驗(yàn)注解分類與說明、分組校驗(yàn)和自定義校驗(yàn),通過這些方法,可以方便地對(duì)Controller、Service等層面的參數(shù)進(jìn)行校驗(yàn),確保數(shù)據(jù)的合法性和一致性,感興趣的朋友跟隨小編一起看看吧2024-11-11