Snow order number generation algorithm

/**
 * Twitter_Snowflake<br>
 * SnowFlake following structure (with each section - apart): <br>
 * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
 * An identity, as long basic types are signed in Java, the most significant bit is the sign bit, 0 is a positive number, a negative number is 1, so the id is generally positive, the highest bit is 0 <br>
 * 41 truncated time (milliseconds), it is noted than 41 times the cross-sectional cut-off storage time of the current time, but the difference between the storage time truncated (cut-off the current time - the start time of cut)
 * Value obtained), where the start time of a truncated, generally the time of our id generator is started, the program specified by our (the following procedure IdWorker class attributes startTime below). Cut-off time 41, 69 may be used in, in T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 <br>
 * 10 data bits machines, nodes may be deployed in 1024, and comprises five datacenterId 5 workerId <br>
 * 12 bit sequence, the count within milliseconds, the count of sequence number 12 of each support node per millisecond (the same machine, the same cut-off time) to produce the ID number 4096 <br>
 * Add up to just 64 for a Long type. <br>
 * Snowflake advantage is that the overall increment in time order, and do not generate collisions ID (as distinguished from the data center ID and machine ID) throughout the distributed system, and high efficiency, tested, can be generated per second Snowflake about 260,000 ID.
 */
public class SnowflakeIdWorker {

    // ============================== Fields ================= ========================== 
    / ** start time cut (2015-01-01) * / 
    Private  Final  Long twepoch = 1420041600000L ;

    / ** -digit share of the machine id * / 
    Private  Final  Long workerIdBits = 5L ;

    / * Data identifying the number of bits occupied by the ID * / 
    Private  Final  Long datacenterIdBits = 5L ;

    / ** The maximum supported machine id, the result is 31 (this shift algorithm can quickly calculate the maximum number of decimal several binary number can represent) * / 
    Private  Final  Long maxWorkerId -1L = ^ (-1L << workerIdBits);

    / ** The maximum data identification id, result 31 is * / 
    Private  Final  Long maxDatacenterId -1L = ^ (-1L << datacenterIdBits);

    / * Sequence number of bits occupied in id * / 
    Private  Final  Long sequenceBits = 12L ;

    / ** machine ID 12 to the left * / 
    Private  Final  Long workerIdShift = sequenceBits;

    / * Data identifying id to the left by 17 (+ 12 is. 5) * / 
    Private  Final  Long datacenterIdShift + = sequenceBits workerIdBits;

    / * Time to cut the left 22 (. 5 + + 12 is. 5) * / 
    Private  Final  Long timestampLeftShift workerIdBits + + = sequenceBits datacenterIdBits;

    / ** generating a mask sequence, here 4095 (0b111111111111 = 0xFFF = 4095) * / 
    Private  Final  Long sequenceMask -1L = ^ (-1L << sequenceBits);

    / ** Work machine ID (~ 31 is 0) * / 
    Private  Long workerId;

    / ** Data Center ID (~ 31 is 0) * / 
    Private  Long datacenterId;

    / ** milliseconds sequence (0 ~ 4095) * / 
    Private  Long Sequence = 0L ;

    / * Last generated ID sectional time * / 
    Private  Long LastTimestamp = -1L ;

    //==============================Constructors=====================================
    /**
     * Constructor
     * @Param workerId Job ID (0 ~ 31)
     * @param datacenterId 数据中心ID (0~31)
     */
    public SnowflakeIdWorker(long workerId, long datacenterId) {
        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));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }

    // ==============================Methods==========================================
    /**
     * Get the next ID (which is thread-safe)
     * @return SnowflakeId
     */
    public synchronized long nextId() {
        long timestamp = timeGen();

        // if the current time is less than the timestamp of the last generation ID, indicating the system clock backoff time should be thrown through the 
        IF (timestamp < LastTimestamp) {
             the throw  new new a RuntimeException (
                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        // If it is generated at the same time, the sequence is performed within milliseconds 
        IF (LastTimestamp == timestamp) {
            Sequence = (+ Sequence. 1) & sequenceMask;
             // millisecond sequence overflow 
            IF (Sequence == 0 ) {
                 // blocking the next millisecond, obtain a new timestamp 
                timestamp = tilNextMillis (LastTimestamp);
            }
        }
        // time stamp change, the sequence milliseconds reset 
        the else {
            sequence = 0L;
        }

        // Last time generation ID sectional 
        LastTimestamp = timestamp;

        // shift to the fight and ORed with the composition 64 ID 
        return ((timestamp - twepoch) << timestampLeftShift) //
                 | (datacenterId << datacenterIdShift) //
                 | (workerId << workerIdShift) //
                 | Sequence;
    }

    /**
     * Blocking a millisecond to the next, until a new timestamp
     * @Param LastTimestamp cut-off time of the last generation ID
     * @Return current timestamp
      * / 
    protected  Long tilNextMillis ( Long LastTimestamp) {
         Long timestamp = TIMEGEN ();
         the while (timestamp <= LastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    /**
     * Returns the current time in milliseconds
     * @Return current time (ms)
      * / 
    protected  Long TIMEGEN () {
         return System.currentTimeMillis ();
    }

    // ============================== the Test ================= ============================ 
    / ** test * / 
    public  static  void main (String [] args) {
        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
        for (int i = 0; i < 1000; i++) {
            long id = idWorker.nextId();
            System.out.println(Long.toBinaryString(id));
            System.out.println(id);
        }
    }
}

 

Guess you like

Origin www.cnblogs.com/keepMoveForevery/p/12576140.html