Rumah >Java >javaTutorial >Cara menjana ID melalui edaran salji SnowFlake tulisan tangan di Jawa

Cara menjana ID melalui edaran salji SnowFlake tulisan tangan di Jawa

PHPz
PHPzke hadapan
2023-04-24 21:34:161084semak imbas

Algoritma SnowFlake

Hasil id yang dijana oleh algoritma SnowFlake ialah integer 64-bit Strukturnya adalah seperti berikut:

Cara menjana ID melalui edaran salji SnowFlake tulisan tangan di Jawa

dibahagikan kepada. empat bahagian:

Perenggan pertama: Bit 1 tidak digunakan dan sentiasa ditetapkan pada 0.

(Oleh kerana bit tertinggi dalam binari ialah bit tanda, 1 mewakili nombor negatif, dan 0 mewakili nombor positif. ID yang dijana biasanya integer positif, jadi bit tertinggi ditetapkan kepada 0)

Segmen Kedua: 41 bit ialah masa milisaat (panjang 41 bit boleh digunakan selama 69 tahun)

Segmen ketiga: 10 bit ialah workerId (panjang 10 bit menyokong penggunaan sehingga 1024 nod)

(10 digit di sini dibahagikan kepada dua bahagian. 5 digit pertama mewakili ID pusat data (0-31) dan bahagian kedua 5 digit mewakili ID mesin (0-31))

Perenggan keempat: 12 digit Mengira dalam milisaat (nombor urutan pengiraan 12-bit menyokong setiap nod yang menjana nombor bersiri ID 4096 setiap milisaat)

Pelaksanaan kod:

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());
    }

}

Kaedah mendapatkan id dalam kod menggunakan bit Pelaksanaan Operasi

Cara menjana ID melalui edaran salji SnowFlake tulisan tangan di Jawa

1 | 00000|0 0000|0000 00000000 //41 digit masa

0|0000000 00000000 00000000 00000000 00000000 00000000 00|0 00 | -digit ID pusat data

0 |0000000 00000000 00000000 00000000 00000000 00|00000|1 1001|0000 00000000 //5 digit ID mesin

0.00000 0000000 00000000 00|00000| urutan

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

0|0001100 10100010 10111110 10001001 01011100 00|10001|1 1001|0000 00000000 //Keputusan 9>Kelebihan SnowFlake :

Semua dijana id meningkat dalam aliran masa ID pendua tidak akan dijana dalam keseluruhan sistem yang diedarkan (kerana terdapat datacenterId dan workerId untuk dibezakan) Kekurangan SnowFlake:

Memandangkan SnowFlake sangat bergantung pada cap masa, perubahan masa akan menyebabkan ralat dalam SnowFlake algoritma.

Atas ialah kandungan terperinci Cara menjana ID melalui edaran salji SnowFlake tulisan tangan di Jawa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam