Heim >Java >javaLernprogramm >So generieren Sie eine ID durch handschriftliche verteilte Schneeflocken-SnowFlake in Java

So generieren Sie eine ID durch handschriftliche verteilte Schneeflocken-SnowFlake in Java

PHPz
PHPznach vorne
2023-04-24 21:34:161081Durchsuche

SnowFlake-Algorithmus

Das Ergebnis der vom SnowFlake-Algorithmus generierten ID ist eine 64-Bit-Ganzzahl. Seine Struktur ist wie folgt:

So generieren Sie eine ID durch handschriftliche verteilte Schneeflocken-SnowFlake in Java

ist in vier Abschnitte unterteilt:

Erster Abschnitt: 1 Bit ist unbenutzt und ist immer auf 0 festgelegt.

(Da das höchste Bit im Binärformat das Vorzeichenbit ist, stellt 1 eine negative Zahl und 0 eine positive Zahl dar. Die generierten IDs sind im Allgemeinen positive Ganzzahlen, daher ist das höchste Bit auf 0 festgelegt)

Zweiter Absatz: 41 Bits sind Millisekunden-Zeiten (die Länge von 41 Bits kann 69 Jahre lang verwendet werden)

Der dritte Absatz: 10 Bits ist die Worker-ID (die Länge von 10 Bits unterstützt die Bereitstellung von bis zu 1024 Knoten)

(Die 10 Bits hier sind in zwei Teile unterteilt, der erste Teil wird durch 5 Bits dargestellt. Der 5-stellige zweite Teil der Rechenzentrums-ID (0-31) stellt die Maschinen-ID (0-31) dar)

Der vierte Absatz: 12-Bit-Anzahl innerhalb von Millisekunden (die 12-Bit-Zählsequenznummer unterstützt jeden Knoten, der 4096 pro Millisekunde ID-Seriennummer generiert)

Code-Implementierung:

import java.util.HashSet;
import java.util.concurrent.atomic.AtomicLong;

public class SnowFlake {

    //时间 41位
    private static long lastTime = System.currentTimeMillis();

    //数据中心ID 5位(默认0-31)
    private long datacenterId = 0;
    private long datacenterIdShift = 5;

    //机房机器ID 5位(默认0-31)
    private long workerId = 0;
    private long workerIdShift = 5;

    //随机数 12位(默认0~4095)
    private AtomicLong random = new AtomicLong();
    private long randomShift = 12;
    //随机数的最大值
    private long maxRandom = (long) Math.pow(2, randomShift);

    public SnowFlake() {
    }

    public SnowFlake(long workerIdShift, long datacenterIdShift){
        if (workerIdShift < 0 ||
                datacenterIdShift < 0 ||
                workerIdShift + datacenterIdShift > 22) {
            throw new IllegalArgumentException("参数不匹配");
        }
        this.workerIdShift = workerIdShift;
        this.datacenterIdShift = datacenterIdShift;
        this.randomShift = 22 - datacenterIdShift - workerIdShift;
        this.maxRandom = (long) Math.pow(2, randomShift);
    }

    //获取雪花的ID
    private long getId() {
        return lastTime << (workerIdShift + datacenterIdShift + randomShift) |
                workerId << (datacenterIdShift + randomShift) |
                datacenterId << randomShift |
                random.get();
    }

    //生成一个新的ID
    public synchronized long nextId() {
        long now = System.currentTimeMillis();

        //如果当前时间和上一次时间不在同一毫秒内,直接返回
        if (now > lastTime) {
            lastTime = now;
            random.set(0);
            return getId();
        }

	//将最后的随机数,进行+1操作
        if (random.incrementAndGet() < maxRandom) {
            return getId();
        }

        //自选等待下一毫秒
        while (now <= lastTime) {
            now = System.currentTimeMillis();
        }

        lastTime = now;
        random.set(0);
        return getId();

    }

    //测试
    public static void main(String[] args) {
        SnowFlake snowFlake = new SnowFlake();
        HashSet<Long> set = new HashSet<>();
        for (int i = 0; i < 10000; i++) {
            set.add(snowFlake.nextId());
        }
        System.out.println(set.size());
    }

}

Die Methode zum Erhalten der ID im Code wird mithilfe von Bitoperationen implementiert

So generieren Sie eine ID durch handschriftliche verteilte Schneeflocken-SnowFlake in Java

1 12 00000 00000000 00000000 00000000 00|10001|0 0000|0000 00000000 //5-stellige Daten Zentrums-ID

0|0000000 00000000 00000000 00000000 00000000 00|. 00000|1 1001|0000 00000000 //5-Bit-Maschinen-ID

oder 0|0000000 00000000 00000000 00000000 00000000 00|00000|0 0000|0000 00000000 //12 Ziffern Reihenfolge

------- ---------------------------------------- ------------------------ --------------------

0|0001100 10100010 10111110 10001001 01011100 00|10001|1 1001|. 0000 00000000 //Ergebnis: 910499571847892992

SnowFlake Vorteile:

Alle generierten IDs steigen entsprechend dem Zeittrend. Im gesamten verteilten System werden keine doppelten IDs generiert (da solche vorhanden sind). datacenterId und workerId zur Unterscheidung) SnowFlake-Nachteile:

Da SnowFlake stark auf Zeitstempel angewiesen ist, führen zeitliche Änderungen zu Fehlern im SnowFlake-Algorithmus.

Das obige ist der detaillierte Inhalt vonSo generieren Sie eine ID durch handschriftliche verteilte Schneeflocken-SnowFlake in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen