编程知识 cdmana.com

Snowflake algorithm to generate ID

Snowflake algorithm id It's a long Type of   Convert to binary yes 64 position   

0   |      00000000000000000000000000000000000000000  |   0000000000|    000000000000
 

The first part : first place 0 The sign bit     Because of the id All positive numbers.   So the first one is 0  ( Mark positive and negative with the first digit 1 A negative number 0 It means a positive number )

The second part :00000000000000000000000000000000000000000  This 41 Bit represents the timestamp of the current server Millisecond value   Because the millisecond value is converted to binary Namely 41 position     The maximum value of the timestamp   It's about 70 year   

The third part :  0000000000  this 10 In a The top five signs machine id  The last five digits indicate colony id    That is to say, machines id The maximum is 2 Of 5 The power minus 1 That is to say 31  colony id The maximum is also 31

The fourth part :000000000000 this 12 Who said Sequence     12 All places are 1 At most 4095    in other words Each machine   Every millisecond can generate at most 4095 individual id

Code example

package com.xiao;


public class IdWorker{

    // Each of the following two 5 position , Add up to 10 Bit working machine id
    private long workerId;    // Work id
    private long datacenterId;   // data id
    //12 Bit's serial number 
    private long sequence;

    public IdWorker(long workerId, long datacenterId, long sequence){
        // sanity check for workerId
        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));
        }
        System.out.printf("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d",
                timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId);

        this.workerId = workerId;
        this.datacenterId = datacenterId;
        this.sequence = sequence;
    }

    // Initial timestamp 
    private long twepoch = 1288834974657L;

    // The length is 5 position 
    private long workerIdBits = 5L;
    private long datacenterIdBits = 5L;
    // Maximum 
    private long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    // Serial number id length 
    private long sequenceBits = 12L;
    // Maximum serial number 
    private long sequenceMask = -1L ^ (-1L << sequenceBits);
    
    // Work id The number of digits that need to be shifted left ,12 position 
    private long workerIdShift = sequenceBits;
   // data id You need to shift the number of digits to the left  12+5=17 position 
    private long datacenterIdShift = sequenceBits + workerIdBits;
    // Timestamps need to be shifted to the left  12+5+5=22 position 
    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    
    // Last time stamp , The initial value is negative 
    private long lastTimestamp = -1L;

    public long getWorkerId(){
        return workerId;
    }

    public long getDatacenterId(){
        return datacenterId;
    }

    public long getTimestamp(){
        return System.currentTimeMillis();
    }

     // next ID generating algorithm 
    public synchronized long nextId() {
        long timestamp = timeGen();

        // Get the current time stamp. If it is less than the last time stamp , Indicates that there is an exception in timestamp acquisition 
        if (timestamp < lastTimestamp) {
            System.err.printf("clock is moving backwards.  Rejecting requests until %d.", lastTimestamp);
            throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds",
                    lastTimestamp - timestamp));
        }

        // Get the current time stamp if it is equal to the last time stamp 
        // explain : Still in the same millisecond , Add... To the serial number 1; Otherwise, the serial number is assigned to 0, from 0 Start .
        if (lastTimestamp == timestamp) {  // 0  - 4095
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0;
        }
        
        // Refresh last timestamp value 
        lastTimestamp = timestamp;

        /**
          *  Return results :
          * (timestamp - twepoch) << timestampLeftShift)  Indicates that the initial timestamp is subtracted from the timestamp , Move the corresponding digit to the left 
          * (datacenterId << datacenterIdShift)  It means that the data will be id Move the corresponding digit to the left 
          * (workerId << workerIdShift)  I'm going to work id Move the corresponding digit to the left 
          * |  It's a bitwise OR operator , for example :x | y, Only when x,y All for 0 It turns out to be 0, In other cases, the result is 1.
          *  Because only the values in the corresponding bits are meaningful , All the others are 0, So the values of each part are calculated  |  You can get the final stitched id
        */
        return ((timestamp - twepoch) << timestampLeftShift) |
                (datacenterId << datacenterIdShift) |
                (workerId << workerIdShift) |
                sequence;
    }

    // Get the timestamp , And compare with the last timestamp 
    private long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    // Get the system timestamp 
    private long timeGen(){
        return System.currentTimeMillis();
    }




    public static void main(String[] args) {
        IdWorker worker = new IdWorker(31,31,0);
        for (int i = 0; i < 100; i++) {
            System.out.println(worker.nextId());
        }
    }

}

 

版权声明
本文为[xiaozhou18]所创,转载请带上原文链接,感谢
https://cdmana.com/2020/12/20201225132517929v.html

Scroll to Top