Maison  >  Article  >  Java  >  Comment générer un identifiant via un flocon de neige distribué manuscrit SnowFlake en Java

Comment générer un identifiant via un flocon de neige distribué manuscrit SnowFlake en Java

PHPz
PHPzavant
2023-04-24 21:34:16988parcourir

Algorithme SnowFlake

Le résultat de l'ID généré par l'algorithme SnowFlake est un entier de 64 bits. Sa structure est la suivante :

Comment générer un identifiant via un flocon de neige distribué manuscrit SnowFlake en Java

est divisé en quatre sections :

Première section : 1 bit est inutilisé et est. toujours fixé à 0 .

(Parce que le bit le plus élevé en binaire est le bit de signe, 1 représente un nombre négatif et 0 représente un nombre positif. Les identifiants générés sont généralement des entiers positifs, donc le bit le plus élevé est fixé à 0)

Deuxième paragraphe : 41 les bits sont en millisecondes (la longueur de 41 bits peut être utilisée pendant 69 ans)

Le troisième paragraphe : 10 bits est le workerId (la longueur de 10 bits prend en charge le déploiement de jusqu'à 1024 nœuds)

(Les 10 bits ici sont divisés en deux parties, la première partie est représentée par 5 bits. La deuxième partie à 5 chiffres de l'ID du centre de données (0-31) représente l'ID de la machine (0-31))

Le quatrième paragraphe : nombre de 12 bits en quelques millisecondes (le numéro de séquence de comptage de 12 bits prend en charge chaque nœud générant 4096 numéros de série d'identification par milliseconde)

Implémentation du code :

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

}

La méthode d'obtention de l'identifiant dans le code est implémentée à l'aide d'opérations sur les bits

Comment générer un identifiant via un flocon de neige distribué manuscrit SnowFlake en Java

1 | 12

0|0001100 10100010 10111110 10001001 01011100 00|00000| 0 0000|0000 00000000 //Heure à 41 chiffres

0|0000000 00000 000 00000000 00000000 00000000 00|10001|0 0000|0000 00000000 //Données à 5 chiffres ID du centre

0|0000000 00000000 00000000 00000000 00000000 00| 00000|1 1001|0000 00000000 // ID de la machine à 5 chiffres

ou 0|0000000 00000000 00000000 00000000 00000000 00|00000|0 0000|0000 00000000 //12 chiffres séquence

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

0|0001100 10100010 10111110 10001001 01011100 00|10001|1 1001| 0000 00000000 //Résultat : 910499571847892992

Avantages SnowFlake :

Tous les identifiants générés augmentent en fonction de la tendance temporelle. Aucun ID en double ne sera généré dans l'ensemble du système distribué (car il y a datacenterId et workerId à distinguer) Inconvénients de SnowFlake : 

En raison de SnowFlake, il s'appuie fortement sur les horodatages, donc les changements d'heure provoqueront des erreurs dans l'algorithme de SnowFlake.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer