All Downloads are FREE. Search and download functionalities are using the official Maven repository.

top.bluesword.util.sequence.Snowflake Maven / Gradle / Ivy

The newest version!
package top.bluesword.util.sequence;

import top.bluesword.util.exception.SwordRuntimeException;

/**
 * 基于Twitter的SnowFlake算法的ID生成工具
 *
 * @author 李林峰
 */
public class Snowflake {

    /**
     * 起始时间戳,用于用当前时间戳减去这个时间戳,算出偏移量
     **/
    private static final long START_TIME = 1530258005750L;

    private long workerIdShift;
    private long dataCenterIdShift;
    private long timestampLeftShift;
    private long sequenceMask;
    private long workerId;
    private long dataCenterId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    /**
     * 基于Snowflake创建分布式ID生成器
     */
    public Snowflake() {
        this(12L);
    }

    /**
     * @param sequenceBits 序列号二进制位数
     */
    public Snowflake(long sequenceBits) {
        this(0L, 0L, sequenceBits, 0L, 0L);
    }

    /**
     * @param dataCenterId 数据中心ID
     * @param workerId     机器ID
     */
    public Snowflake(long dataCenterId, long workerId) {
        this(5L, 5L, 12L, dataCenterId, workerId);
    }

    /**
     * @param workerIdBits     机器ID二进制位数
     * @param dataCenterIdBits 数据中心ID二进制位数
     * @param sequenceBits     序列号二进制位数
     * @param dataCenterId     数据中心ID
     * @param workerId         机器ID
     */
    public Snowflake(long workerIdBits, long dataCenterIdBits, long sequenceBits, long dataCenterId, long workerId) {
        long maxDataCenterId = ~(-1L << dataCenterIdBits);
        if (dataCenterId > maxDataCenterId || dataCenterId < 0) {
            throw new SwordRuntimeException(String.format("数据中心ID不可以大于  %d 或小于 0", maxDataCenterId));
        }
        long maxWorkerId = ~(-1L << workerIdBits);
        if (workerId > maxWorkerId || workerId < 0) {
            throw new SwordRuntimeException(String.format("工作机器ID不可以大于  %d 或小于 0", maxWorkerId));
        }
        this.dataCenterId = dataCenterId;
        this.workerId = workerId;
        this.sequenceMask = ~(-1L << sequenceBits);
        this.workerIdShift = sequenceBits;
        this.dataCenterIdShift = sequenceBits + workerIdBits;
        this.timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits;
    }

    /**
     * 获取ID
     * @return ID
     */
    public synchronized Long nextId() {
        long timestamp = System.currentTimeMillis();
        if (timestamp < lastTimestamp) {
            throw new SwordRuntimeException(String.format("时间回退,请在 %d 毫秒后申请ID",lastTimestamp - timestamp));
        }
        if (lastTimestamp == timestamp) {
            //通过位与运算保证计算的结果在范围内
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = this.tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        return ((timestamp - START_TIME) << timestampLeftShift) | (dataCenterId << dataCenterIdShift)
                | (workerId << workerIdShift) | sequence;
    }

    /**
     * 保证返回的毫秒数在参数之后(阻塞到下一个毫秒,直到获得新的时间戳)
     */
    private long tilNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy