分佈式惟一ID生成算法-雪花算法

在咱們的工做中,數據庫某些表的字段會用到惟一的,趨勢遞增的訂單編號,咱們將介紹兩種方法,一種是傳統的採用隨機數生成的方式,另一種是採用當前比較流行的「分佈式惟一ID生成算法-雪花算法」來實現。html

 

1、時間戳隨機數生成惟一IDjava

咱們寫一個for循環,用RandomUtil.generateOrderCode()生成1000個惟一ID,執行結果咱們會發現出現重複的ID。git

/**
 * 隨機數生成util
 **/
public class RandomUtil {
    private static final SimpleDateFormat dateFormatOne=new SimpleDateFormat("yyyyMMddHHmmssSS");
 
    private static final ThreadLocalRandom random=ThreadLocalRandom.current();
    //生成訂單編號-方式一
    public static String generateOrderCode(){
        //TODO:時間戳+N爲隨機數流水號
        return dateFormatOne.format(DateTime.now().toDate()) + generateNumber(4);
    }
 
    //N爲隨機數流水號
    public static String generateNumber(final int num){
        StringBuffer sb=new StringBuffer();
        for (int i=1;i<=num;i++){
            sb.append(random.nextInt(9));
        }
        return sb.toString();
    }
}

鑑於此種「基於隨機數生成」的方式在高併發的場景下並不符合咱們的要求,接下來,咱們將介紹另一種比較流行的、典型的方式,即「分佈式惟一ID生成算法-雪花算法」來實現。github

對於「雪花算法」的介紹,各位小夥伴能夠參考Github上的這一連接,我以爲講得仍是挺清晰的:https://github.com/souyunku/SnowFlake,詳細的Debug在這裏就不贅述了,下面截取了部分概述:算法

 

2、分佈式惟一ID生成算法-雪花算法數據庫

咱們寫一個for循環,用SNOW_FLAKE.nextId() 生成1000個惟一ID,發現不會出現重複的。併發

/** * 雪花算法
*/ public class SnowFlake { //起始的時間戳 private final static long START_STAMP = 1480166465631L; //每一部分佔用的位數 private final static long SEQUENCE_BIT = 12; //序列號佔用的位數 private final static long MACHINE_BIT = 5; //機器標識佔用的位數 private final static long DATA_CENTER_BIT = 5;//數據中心佔用的位數 //每一部分的最大值 private final static long MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_BIT); private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); //每一部分向左的位移 private final static long MACHINE_LEFT = SEQUENCE_BIT; private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT; private long dataCenterId; //數據中心 private long machineId; //機器標識 private long sequence = 0L; //序列號 private long lastStamp = -1L;//上一次時間戳 public SnowFlake(long dataCenterId, long machineId) { if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) { throw new IllegalArgumentException("dataCenterId can't be greater than MAX_DATA_CENTER_NUM or less than 0"); } if (machineId > MAX_MACHINE_NUM || machineId < 0) { throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0"); } this.dataCenterId = dataCenterId; this.machineId = machineId; } //產生下一個ID public synchronized long nextId() { long currStamp = getNewStamp(); if (currStamp < lastStamp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id"); } if (currStamp == lastStamp) { //相同毫秒內,序列號自增 sequence = (sequence + 1) & MAX_SEQUENCE; //同一毫秒的序列數已經達到最大 if (sequence == 0L) { currStamp = getNextMill(); } } else { //不一樣毫秒內,序列號置爲0 sequence = 0L; } lastStamp = currStamp; return (currStamp - START_STAMP) << TIMESTAMP_LEFT //時間戳部分 | dataCenterId << DATA_CENTER_LEFT //數據中心部分 | machineId << MACHINE_LEFT //機器標識部分 | sequence; //序列號部分 } private long getNextMill() { long mill = getNewStamp(); while (mill <= lastStamp) { mill = getNewStamp(); } return mill; } private long getNewStamp() { return System.currentTimeMillis(); } }

綜上,咱們在高併發大量生成惟一ID時,避免生成重複ID,須要用第二種雪花算法生成。app

 

原文出處:https://www.cnblogs.com/haly/p/11470473.htmlless

相關文章
相關標籤/搜索