Principle and "Java knowledge application" Java snowflake algorithm

SnowFlake algorithm, Twitter is an open source distributed id generation algorithm. Its core idea is: use long-type numbers as a 64 bit globally unique id. Applications in a distributed system is very extensive, and the introduction of ID timestamp, basically to keep from growing.

This 64 bit, where a bit is not used, bit 41 is then used as one of the few milliseconds, with 10 bit as the working machine id, 12 bit as a sequence number.

Let me give you an example, such as the 64 bit below the long-type numbers:

The first part is a bit: 0, this is meaningless, because the first one bit is the sign bit, 1 for negative, 0 for a positive number.

The second part is a 41 bit: indicates the timestamp.

The third part is the 5 bit: indicates that the room id, 10001.

The fourth part is the 5 bit: indicates that the machine id, 1 1001.

The fifth portion 12 is a bit: indicates the number, that is simultaneously generated within a millisecond on a machine room number of id, 000,000,000,000.

In simple terms, you have a service Suppose you want to generate a globally unique id, then you can send a request to deploy the system SnowFlake algorithm by the system SnowFlake algorithm to generate a unique id.

The SnowFlake algorithm system of course, is to know where their rooms and machines, such as room id = 17, the machine id = 12.

Then, after receiving the request, we will use the first bit generated in a manner SnowFlake calculation algorithm of the system a 64 bit long type id, the first bit in the 64 th bit is meaningless.

Then 41 bit, you can use the current timestamp (in milliseconds), and then the upper room 5 id bit set, bit 5 there is disposed on the machine id. 

Finally, determine what, in this milliseconds on this machine room a current, which is the first of several requests to the request id generated a cumulative sequence number, as the last 12 bit.

Snow algorithm code:

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

/**
 * Snow algorithm
 */
public class SnowFlake {

    Private  Final  static  Long twepoch = 12888349746579L ;
     // machine identification bits 
    Private  Final  static  Long workerIdBits = 5L ;
     // data center identifier bits 
    Private  Final  static  Long datacenterIdBits = 5L ;
     // increment the number of bits in the millisecond 
    Private  Final  static  Long sequenceBits 12L = ;
     // machine ID 12 shift left 
    private  Final  static  Long workerIdShift = sequenceBits;
     // data center ID 17 left 
    private Final  static  Long datacenterIdShift + = sequenceBits workerIdBits;
     // time in milliseconds left 22 
    Private  Final  static  Long timestampLeftShift workerIdBits + + = sequenceBits datacenterIdBits;
     // Sequence mask, will not exceed the upper limit to ensure sequnce 
    Private  Final  static  Long sequenceMask ^ = -1L (-1L << sequenceBits);
     // last timestamp 
    Private  static  Long LastTimestamp = -1L ;
     // sequence 
    Private  Long sequence = 0L ;
     // server ID 
    Private long workerId = 1L;
    private static long workerMask = -1L ^ (-1L << workerIdBits);
    //进程编码
    private long processId = 1L;
    private static long processMask = -1L ^ (-1L << datacenterIdBits);

    private static SnowFlake snowFlake = null;

    static{
        snowFlake = new SnowFlake();
    }
    public static synchronized long nextId(){
        return snowFlake.getNextId();
    }

    Private Snowflake () {
         // Get machine code 
        the this .workerId = the this .getMachineNum ();
         // get the process coding 
        the RuntimeMXBean RuntimeMXBean = ManagementFactory.getRuntimeMXBean ();
         the this . .processId = Long.valueOf (runtimeMXBean.getName () Split ( "@") [0 ]) longValue in ().;

        // to avoid exceeding the maximum encoding 
        the this .workerId = workerId & workerMask;
         the this .processId = processId & processMask;
    }

    public  the synchronized  Long getNextId () {
         // Get timestamp 
        Long timestamp = TIMEGEN ();
         // if the timestamp is lower than the previous timestamp error 
        IF (timestamp < LastTimestamp) {
             the try {
                 the throw  new new . Exception ( "Clock Backwards refusing Moved Generate for ID to "+ (LastTimestamp - timestamp) +" milliseconds " );
            } catch (Exception e) {
                e.printStackTrace ();
            }
        }
        // If the timestamp and the timestamp of the last time the same 
        IF (LastTimestamp == timestamp) {
             // the current milliseconds, +1, and sequence to ensure that does not exceed the upper limit sequenceMask 
            sequence = (+ sequence. 1) & sequenceMask;
             IF (sequence == 0 ) {
                 // this millisecond count is full, the next second waiting 
                timestamp = tilNextMillis (LastTimestamp);
            }
        } else {
            sequence = 0;
        }
        LastTimestamp = timestamp;
         // ID offset composition generate a final ID, and returns the ID 
        Long nextId = ((timestamp - twepoch) << timestampLeftShift) | (processId << datacenterIdShift) | (workerId << workerIdShift) | Sequence;
         return nextId ;
    }

    /**
     * Get the timestamp and timestamp again until the acquisition of different existing
     * @Param LastTimestamp
     * @Return next timestamp
      * / 
    Private  Long tilNextMillis ( Final  Long LastTimestamp) {
         Long timestamp = the this .timeGen ();
         the while (timestamp <= LastTimestamp) {
            timestamp = this.timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }

    /**
     * Get machine code
     * @return
     */
    private long getMachineNum(){
        long machinePiece;
        StringBuilder sb = new StringBuilder();
        Enumeration<NetworkInterface> e = null;
        try {
            e = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e1) {
            e1.printStackTrace ();
        }
        while (e.hasMoreElements()) {
            NetworkInterface ni = e.nextElement();
            sb.append(ni.toString());
        }
        machinePiece = sb.toString().hashCode();
        return machinePiece;
    }

    public static void main(String[] args) {
        new SnowFlake().getNextId();
    }
}

Reference: https://blog.csdn.net/lq18050010830/article/details/89845790

Guess you like

Origin www.cnblogs.com/jssj/p/12235757.html