Distributed generation ID - Snow algorithm

Snowflake algorithm is a classical algorithm of distributed generation globally unique ID, the interpretation algorithms plethora of online about snow, mostly copy to copy, here refer to the work of God's great elephant ID generator blog, Twitter snowflakes algorithm (Java)

Online tutorials general there are two problems:

1. Machine ID (. 5 bits) and the data center ID (. 5-bit) configuration is not resolved, when distributed deployment will use the same configuration, though there is any risk of duplicate ID.

2. When used need to be instantiated object tools are not formed out of the box.

In this paper, two solutions for the above problems, the author's solution, WorkId hostName generated using the server, dataCenterId generated using IP, this can be prevented to maximize the machine code 10 is repeated, but since the two ID can not exceed 32, can only take the remainder or hard to avoid repetition, but the actual use, hostName and IP configuration generally continuous or similar, if not exactly the case of 32-bit apart, there would be no problem, moreover, hostName and IP simultaneously separated by 32 more it is almost impossible things usually do a distributed deployment, generally no more than 10 containers.

Using the above method can be used snow zero configuration algorithm, the algorithm set theory snow 10 may be machine code 1024 nodes, using the docker production configuration is generally a compiler, and then distributed to different containers deployed, there will be different configuration, where other companies do not know how to solve, even if a method of using a set of configuration, then read different configurations depending on the runtime container, but the container allocated to each ID, 1024 th (in most cases no so much), it seems unlikely to resolve this issue for another day after the bank added.

Package com.feicent.util; 

Import org.apache.commons.lang3.RandomUtils;
 Import org.apache.commons.lang3.StringUtils;
 Import org.apache.commons.lang3.SystemUtils; 

Import java.net.Inet4Address;
 Import Java. net.UnknownHostException; 

/ ** 
 * Twitter_Snowflake <br> 
 * https://blog.csdn.net/u012488504/article/details/82194495 
 * Snowflake following structure (with each section - apart): <br> 
 * 0 - 0000000000 0 0000000000 0000000000 0000000000 - 0000000000 - 000000000000 <br> 
 * 1-bit identifier, 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 cut 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 is) / (1000L * 60 * 60 * 24 * 365) = 69 <br> 
 * 10-bit data bit machine, can be deployed in 1024 nodes, and including 5 datacenterId <br> 5 workerId 
 * 12 sequence 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> 
 advantage * SnowFlake 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, each Snowflake s capable of producing about 260,000 ID. 
 * / 
Public  class SnowflakeIdWorker { 

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

    / **The median share of machine id * / 
    Private  Final  Long workerIdBits = 5L ; 

    / ** data to identify the number of bits occupied by 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 binary number can represent several) * / 
    Private  Final  Long maxWorkerId -1L = ^ (-1L << workerIdBits); 

    / ** the maximum data identification id, result is 31 is * / 
    Private  Final  Long maxDataCenterId -1L = ^ (-1L << dataCenterIdBits); 

    / ** sequence representing the median 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; 

    / ** 22 to the left cut-off time (. 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 ; 

    / ** previously generated ID truncated time * / 
    Private  Long LastTimestamp = -1L ; 

    Private  static SnowflakeIdWorker idWorker; 

    static {
         Long workerId = getWorkId ();
         Long dataCenterId = getDataCenterId (); 
        System.out.println ( "workerId =" + workerId + ", dataCenterId =" + dataCenterId);
        idWorker = new SnowflakeIdWorker(workerId, dataCenterId);
    }

    //==============================Constructors=====================================
    /**
     * 构造函数
     * @param workerId 工作ID (0~31)
     * @param dataCenterId 数据中心ID (0~31)
     */
    public SnowflakeIdWorker(long workerId, long dataCenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("workerId can't be greater than %d or less than 0", maxWorkerId));
        }
        if (dataCenterId > maxDataCenterId || dataCenterId < 0) {
            throw new IllegalArgumentException(String.format("dataCenterId can't be greater than %d or less than 0", maxDataCenterId));
        }
        this.workerId = workerId;
        this.dataCenterId = dataCenterId;
    }

    // ==============================Methods==========================================
    /**
     * 获得下一个ID (该方法是线程安全的)
     * @returnSnowflakeId
      * / 
    public  the 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 ID for refusing to generate% 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;
             //Serial overrun milliseconds 
            IF (Sequence == 0 ) {
                 // blocking the next millisecond, obtain a new timestamp 
                timestamp = tilNextMillis (LastTimestamp); 
            } 
        } 
        // timestamp changes milliseconds reset sequence 
        the else { 
            Sequence = 0L ; 
        } 

        // last time generation ID sectional 
        LastTimestamp = timestamp; 

        // shift to fight and consisting of 64-bit ID ORed together 
        return ((timestamp - twepoch) << timestampLeftShift)
                 | (dataCenterId << dataCenterIdShift)
                 | (workerId << workerIdShift)
                 |Sequence; 
    } 

    / ** 
     * obstruction to the next millisecond, until a new timestamp 
     * @param LastTimestamp time cut previously generated 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();
    }

    private static long getWorkId(){
        try {
            String hostAddress = Inet4Address.getLocalHost().getHostAddress();
            System.out.println("hostAddress: " + hostAddress);
            int[] ints = StringUtils.toCodePoints(hostAddress);
            int sums = 0;
            for(int b : ints){
                sums += b;
            }
            return (Long ) (32% sums ); 
        } the catch (UnknownHostException E) {
             // If the acquisition has failed, the backup using a random number 
            return RandomUtils.nextLong (0, 32 ); 
        } 
    } 

    Private  static  Long getDataCenterId () { 
        System.out.println ( "of hostName:" + SystemUtils.getHostName ());
         int [] = INTS StringUtils.toCodePoints (SystemUtils.getHostName ());
         int sums = 0 ;
         for ( int I: INTS) { 
            sums + = I; 
        }
        return (long)(sums % 32);
    }

    /**
     * 静态工具类
     *
     * @return
     */
    public static Long generateId(){
        return idWorker.nextId();
    }

    /** 测试 */
    public static void main(String[] args) {
        System.out.println(System.currentTimeMillis());
        long startTime = System.nanoTime();
        int count = 1000000;
        for (int i = 0; i < count; i++) {
            Long ID = SnowflakeIdWorker.generateId ();
             // System.out.println (ID); 
        } 
        System.out.println ( "generated [" + count + "] Processed Total Article ID:" + (System.nanoTime () - the startTime) / 1000000 + "MS" ); 
    } 
}

 

Guess you like

Origin www.cnblogs.com/yzuzhang/p/12054185.html