분산 식 자체 성장 ID (트 위 터 의 Snowflake JAVA 구현 방안)

/**<p>   :</p>
 * <p>  :	com.zdb.module.test</p>
 * <p>   :IdWorker.java</p>
 * <p>    :</p>
 * <p>  :2015-5-23-  1:17:49</p>
 * Copyright (c) 2015singno  -    
 */
package com.zdb.module.test;

/**<p>  :IdWorker.java</p>
 * <p>  :      ID</p>
 * <pre>
 *     Twitter  Snowflake JAVA        
 * </pre>
 * @author    
 * @date 2015-5-23   1:17:49
 * @version 1.0.0
 */
public class IdWorker {
	
	private final long workerId;
	private final static long twepoch = 1288834974657L;
	private long sequence = 0L;
	private final static long workerIdBits = 4L;
	public final static long maxWorkerId = -1L ^ -1L << workerIdBits;
	private final static long sequenceBits = 10L;

	private final static long workerIdShift = sequenceBits;
	private final static long timestampLeftShift = sequenceBits + workerIdBits;
	public final static long sequenceMask = -1L ^ -1L << sequenceBits;

	private long lastTimestamp = -1L;

	public IdWorker(final long workerId) {
	    super();
	    if (workerId > this.maxWorkerId || workerId < 0) {
	        throw new IllegalArgumentException(String.format(
	                "worker Id can't be greater than %d or less than 0",
	                this.maxWorkerId));
	    }
	    this.workerId = workerId;
	}

	public synchronized long nextId() {
	    long timestamp = this.timeGen();
	    if (this.lastTimestamp == timestamp) {
	        this.sequence = (this.sequence + 1) & this.sequenceMask;
	        if (this.sequence == 0) {
	            System.out.println("###########" + sequenceMask);
	            timestamp = this.tilNextMillis(this.lastTimestamp);
	        }
	    } else {
	        this.sequence = 0;
	    }
	    if (timestamp < this.lastTimestamp) {
	        try {
	            throw new Exception(
	                    String.format(
	                            "Clock moved backwards.  Refusing to generate id for %d milliseconds",
	                            this.lastTimestamp - timestamp));
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	    }

	    this.lastTimestamp = timestamp;
	    long nextId = ((timestamp - twepoch << timestampLeftShift))
	            | (this.workerId << this.workerIdShift) | (this.sequence);
	    System.out.println("timestamp:" + timestamp + ",timestampLeftShift:"
	            + timestampLeftShift + ",nextId:" + nextId + ",workerId:"
	            + workerId + ",sequence:" + sequence);
	    return nextId;
	}

	private long tilNextMillis(final long lastTimestamp) {
	    long timestamp = this.timeGen();
	    while (timestamp <= lastTimestamp) {
	        timestamp = this.timeGen();
	    }
	    return timestamp;
	}

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


	public static void main(String[] args){
	    IdWorker worker2 = new IdWorker(2);
	    System.out.println(worker2.nextId());
	}
	

}

좋은 웹페이지 즐겨찾기