欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

簡介

雪花 (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)建方式及比較代碼示例

    這篇文章主要介紹了Java多線程中線程的兩種創(chuàng)建方式及比較代碼示例,簡單介紹了線程的概念,并行與并發(fā)等,然后通過實(shí)例代碼向大家展示了線程的創(chuàng)建,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • 劍指Offer之Java算法習(xí)題精講二叉樹與N叉樹

    劍指Offer之Java算法習(xí)題精講二叉樹與N叉樹

    跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會(huì)忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會(huì)發(fā)現(xiàn)質(zhì)的變化
    2022-03-03
  • Spring?Boot中獲取request的三種方式及請(qǐng)求過程

    Spring?Boot中獲取request的三種方式及請(qǐng)求過程

    這篇文章主要介紹了Spring?Boot當(dāng)中獲取request的三種方式,包括請(qǐng)求過程流程分析及response常用API,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • java實(shí)現(xiàn)文件上傳到服務(wù)器

    java實(shí)現(xiàn)文件上傳到服務(wù)器

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)文件上傳到服務(wù)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Java開發(fā)微信Navicat支付完整版

    Java開發(fā)微信Navicat支付完整版

    這篇文章主要介紹了Java開發(fā)微信Navicat支付完整版,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Java源碼解析HashMap的tableSizeFor函數(shù)

    Java源碼解析HashMap的tableSizeFor函數(shù)

    今天小編就為大家分享一篇關(guān)于Java源碼解析HashMap的tableSizeFor函數(shù),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • SpringBoot?Cache?二級(jí)緩存的使用

    SpringBoot?Cache?二級(jí)緩存的使用

    本文主要介紹了SpringBoot?Cache?二級(jí)緩存的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 使用JMF實(shí)現(xiàn)java視頻播放器

    使用JMF實(shí)現(xiàn)java視頻播放器

    這篇文章主要為大家詳細(xì)介紹了使用JMF實(shí)現(xiàn)java視頻播放器的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 聊聊springboot靜態(tài)資源加載的規(guī)則

    聊聊springboot靜態(tài)資源加載的規(guī)則

    這篇文章主要介紹了springboot靜態(tài)資源加載的規(guī)則,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Spring?中使用?Validation?注解校驗(yàn)參數(shù)的方法

    Spring?中使用?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

最新評(píng)論