最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現(xiàn)雪花算法的工具類介紹

 更新時間:2023年05月23日 16:13:12   作者:三省同學(xué)  
雪花 (SnowFlake )算法是一種分布式唯一ID生成算法,可以生成全局唯一的ID標(biāo)識符,就像自然界中雪花一般沒有相同的雪花,本文和大家分享了一個雪花算法工具類,需要的可以收藏一下

簡介

雪花 (SnowFlake )算法是一種分布式唯一ID生成算法,可以生成全局唯一的ID標(biāo)識符,就像自然界中雪花一般沒有相同的雪花。它的核心思想是將一個64位的整數(shù)分成4部分,分別是:

  • 1位標(biāo)識符:即最高位,始終為0,用于區(qū)分正數(shù)和負數(shù)。
  • 41位時間戳:表示生成ID的時間戳,精確到毫秒級別,可以使用69年。
  • 10位數(shù)據(jù)中心ID:表示數(shù)據(jù)中心的編號,可以支持1024個數(shù)據(jù)中心。
  • 12位機器ID:表示機器的編號,可以支持4096臺機器。

snowflake生成的ID整體上按照時間自增排序,并且整個分布式系統(tǒng)內(nèi)不會產(chǎn)生ID碰撞(由datacenter和workerId作區(qū)分),并且效率較高。

在同一毫秒內(nèi),不同的機器或數(shù)據(jù)中心可以生成不同的序列號,通過這種方式保證了生成的ID的唯一性。另外,由于時間戳占據(jù)了64位整數(shù)的高位部分,因此生成的ID是越來越大的,可以滿足一些需要按照時間順序排序的場景需求。

雪花算法的優(yōu)點在于:

  • 簡單易實現(xiàn):主要依賴于時間戳、數(shù)據(jù)中心ID和機器ID三個參數(shù),實現(xiàn)起來比較簡單。
  • 唯一性:生成的ID具有全局唯一性,可以滿足分布式系統(tǒng)的需求。
  • 時間有序:生成的ID是按照時間有序遞增的,可以滿足一些需要按照時間順序排序的場景需求,存入數(shù)據(jù)庫中,索引效率高。。
  • 可擴展性:可以根據(jù)需要增加數(shù)據(jù)中心ID和機器ID的位數(shù),支持更多的數(shù)據(jù)中心和機器。
  • 高性能高可用:生成時不依賴于數(shù)據(jù)庫,完全在內(nèi)存中生成。
  • 容量大:每秒中能生成數(shù)百萬的自增ID。

但是,雪花算法也存在一些缺點:

  • 依賴于系統(tǒng)時鐘:如果系統(tǒng)時鐘回撥,則可能會生成重復(fù)的ID。
  • 數(shù)據(jù)中心ID和機器ID需要手動分配:需要手動配置數(shù)據(jù)中心ID和機器ID,不太方便管理。
  • 機器編號有限:12位機器ID只能支持4096臺機器,如果需要支持更多的機器,則需要增加機器ID的位數(shù)。

綜上所述,雪花算法是一種簡單易實現(xiàn)、具有唯一性和時間有序性的分布式ID生成算法,適用于分布式系統(tǒng)中的唯一ID標(biāo)識符的生成。

Java實現(xiàn)

public class Snowflake {
    // 開始時間戳,一般為項目啟動時間
    private final long twepoch = 1288834974657L;
    // 機器ID所占的位數(shù)
    private final long workerIdBits = 5L;
    // 數(shù)據(jù)標(biāo)識ID所占的位數(shù)
    private final long datacenterIdBits = 5L;
    // 支持的最大機器ID,結(jié)果是31
    private final long maxWorkerId = ~(-1L << workerIdBits);
    // 支持的最大數(shù)據(jù)標(biāo)識ID,結(jié)果是31
    private final long maxDatacenterId = ~(-1L << datacenterIdBits);
    // 序列號所占的位數(shù)
    private final long sequenceBits = 12L;
    // 機器ID向左移12位
    private final long workerIdShift = sequenceBits;
    // 數(shù)據(jù)標(biāo)識ID向左移17位(12+5)
    private final long datacenterIdShift = sequenceBits + workerIdBits;
    // 時間戳向左移22位(5+5+12)
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    // 生成序列的掩碼,這里是4095
    private final long sequenceMask = ~(-1L << sequenceBits);

    private long workerId; // 機器ID
    private long datacenterId; // 數(shù)據(jù)標(biāo)識ID
    private long sequence = 0L; // 序列號
    private long lastTimestamp = -1L; // 上次生成ID的時間戳

    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; // 序列號自增
            if (sequence == 0) { // 序列號超過最大值,則等待下一個時間戳
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L; // 序列號重置為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實現(xiàn)版本,支持高并發(fā)、低延遲、高可用等特點。使用方式:

Snowflake snowflake = new Snowflake(workerId, datacenterId);
long id = snowflake.nextId();

2.百度的UidGenerator:是基于Twitter的snowflake算法改進而來的,支持高性能、高可用、高并發(fā)等特點。使用方式:

UidGenerator uidGenerator = UidGenerator.getUidGenerator();
long id = uidGenerator.getUID();

3.美團的Leaf:是一款高性能、輕量級的分布式ID生成器,支持多種ID生成算法,包括Snowflake算法。使用方式:

SegmentIDGenImpl idGen = new SegmentIDGenImpl();
idGen.init();
long id = idGen.getId();

4.阿里巴巴的nacos:是一款輕量級的服務(wù)注冊與發(fā)現(xiàn)工具,其中包含了雪花算法的Java實現(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實現(xiàn)雪花算法的工具類介紹的文章就介紹到這了,更多相關(guān)Java雪花算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Springboot RestTemplate 簡單使用解析

    Springboot RestTemplate 簡單使用解析

    這篇文章主要介紹了Springboot RestTemplate 簡單使用解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-08-08
  • Java別名Alias是如何工作的

    Java別名Alias是如何工作的

    這篇文章主要介紹了Java別名Alias是如何工作的,別名的問題是,當(dāng)用戶寫入特定對象時,其他幾個引用的所有者不希望該對象發(fā)生更改,下文相關(guān)介紹需要的小伙伴可以參考一下
    2022-04-04
  • java -D參數(shù)設(shè)置系統(tǒng)屬性無效問題及解決

    java -D參數(shù)設(shè)置系統(tǒng)屬性無效問題及解決

    這篇文章主要介紹了java -D參數(shù)設(shè)置系統(tǒng)屬性無效問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • java求余的技巧匯總

    java求余的技巧匯總

    這篇文章主要給大家介紹了關(guān)于java求余技巧的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 基于SpringBoot+FFmpeg+ZLMediaKit實現(xiàn)本地視頻推流

    基于SpringBoot+FFmpeg+ZLMediaKit實現(xiàn)本地視頻推流

    文章介紹了如何在服務(wù)器上安裝和配置ZLMediaKit和FFmpeg,以及如何使用SpringBoot實現(xiàn)視頻推流和播放功能,包括環(huán)境準(zhǔn)備、后端實現(xiàn)和使用說明,涵蓋了推流和播放的完整流程,需要的朋友可以參考下
    2025-11-11
  • Docker?DockerFile部署java?jar項目包及Mysql和Redis的詳細過程

    Docker?DockerFile部署java?jar項目包及Mysql和Redis的詳細過程

    Dockerfile是一種用于構(gòu)建Docker鏡像的文件格式,可以通過Dockerfile部署Java項目,這篇文章主要給大家介紹了關(guān)于Docker?DockerFile部署java?jar項目包及Mysql和Redis的詳細過程,需要的朋友可以參考下
    2023-12-12
  • Java實現(xiàn)的連續(xù)奇數(shù)(n+2*x)是合數(shù)的算法題暴力算法

    Java實現(xiàn)的連續(xù)奇數(shù)(n+2*x)是合數(shù)的算法題暴力算法

    這篇文章主要介紹了Java實現(xiàn)的連續(xù)奇數(shù)(n+2*x)是合數(shù)的算法題暴力算法,本文包含運算結(jié)果和實現(xiàn)代碼,需要的朋友可以參考下
    2014-09-09
  • 淺談spring-boot 允許接口跨域并實現(xiàn)攔截(CORS)

    淺談spring-boot 允許接口跨域并實現(xiàn)攔截(CORS)

    本篇文章主要介紹了淺談spring-boot 允許接口跨域并實現(xiàn)攔截(CORS),具有一定的參考價值,有興趣的可以了解一下
    2017-08-08
  • Java設(shè)計模式之迭代器模式解析

    Java設(shè)計模式之迭代器模式解析

    這篇文章主要介紹了Java設(shè)計模式之迭代器模式解析,迭代器模式提供一個對象來順序訪問聚合對象中的一系列數(shù)據(jù),而不暴露聚合對象的內(nèi)部表示,本文提供了部分代碼,需要的朋友可以參考下
    2023-09-09
  • Java線程狀態(tài)運行原理解析

    Java線程狀態(tài)運行原理解析

    這篇文章主要介紹了Java線程狀態(tài)運行原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12

最新評論

光泽县| 库车县| 丰县| 大方县| 商水县| 林甸县| 宝鸡市| 高尔夫| 高阳县| 永城市| 扶沟县| 湟中县| 云龙县| 凌源市| 南昌县| 怀安县| 绥滨县| 富川| 林芝县| 体育| 乌鲁木齐市| 海阳市| 梁山县| 鲁山县| 曲水县| 从江县| 延庆县| 军事| 吉水县| 大新县| 乐都县| 丰都县| 虞城县| 新巴尔虎左旗| 涟水县| 柘城县| 繁峙县| 霍山县| 金平| 英山县| 七台河市|