欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java版雪花算法

程序员文章站 2022-03-08 17:53:39
...

一、雪花算法图

java版雪花算法

二、java 雪花算法代码

1.雪花算法,分为三块,分别是时间,机器码,序列化

public class SnowFlakeUtil {

  / **
 * 开始时间
 */
private final long START_TIMESTAMP = 1577808000000L; //2020-01-01
/**
 * 机器位移数据
 */
private final static long WORK_ID_BIT = 10L;

/**
 * 机器标识最大值,最多1024台
 */
private final static long WORK_ID_MAX = 1L << WORK_ID_BIT;

/**
 * 序列化唯一数据
 */
private final static long SEQUENCE_BIT = 12L;


/**
 * 序列化最大值,4095个数据
 */
private final static long SEQUENCE_MAX = 1L<<SEQUENCE_BIT;

/**
 * 时间位移数据
 */
private final static long TIME_BIT = WORK_ID_BIT+SEQUENCE_BIT;

/**
 * 上一毫秒时间戳
 */
private long BEFORE_TIME = 0L;

/**
 * 序列化初始值
 */
private  long SEQUENCE_START = 0L;


 public SnowFlakeUtil(){
}

/**
 * 获取当前最新的时间轴
 * @return
 */
private long nowTime(){
    return System.currentTimeMillis();
}

/**
 * 等待下一毫米
 * @return
 */
private long getNextMill(){
    long nextTime = nowTime();
    while (nextTime <= BEFORE_TIME) {
        nextTime = nowTime();
    }
    return nextTime;
}
/**
 * 分布式id,线程安全
 * @return
 */
public synchronized long nextId(long workId){
    if(workId>WORK_ID_MAX){
        throw new RuntimeException("机器码超过指定的最大机器码数据");
    }
    long time = nowTime();
    //当前时间戳小于上一秒时间戳,就意味着时间回拨,导致的
    if(BEFORE_TIME>0&&time<BEFORE_TIME){
        throw new RuntimeException("时间回拨");
    }
    //如果时间相同,就判断上一个序列化值
    if(time==BEFORE_TIME){
        SEQUENCE_START = SEQUENCE_START+1;
        //大于的话,就意味着这一毫秒,已经没有序列值,就一直等待到下一毫秒
        if(SEQUENCE_START>SEQUENCE_MAX){
            time = this.getNextMill();
            SEQUENCE_START = 0L;
        }
    }else{
        //时间不同,就意味着开始
        SEQUENCE_START = 0L;
    }
    //初始最新时间
    BEFORE_TIME = time;
    return (time - START_TIMESTAMP) << TIME_BIT //时间戳部分
            | workId << SEQUENCE_BIT       //j机器码部分
            | SEQUENCE_START;  //j序列化部分

}

public static void main(String arg[]){

    SnowFlakeUtil snowFlakeUtil = new SnowFlakeUtil();
    for(int i=0;i<2000;i++) {
        System.out.println(snowFlakeUtil.nextId(1L));
    }
}

三、雪花算法缺陷

1:由于服务器会进行时间校正,就会出现服务器时间回拨,这时,雪花算法就会出现一段时间生产不了,影响服务使用。
2:由于雪花long类型是64bit,前端用long会失精度,前端要用字符串类型
3:百度的UidGenerator分布式ID解决了时间回拨问题,可以用它