国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術(shù)文章
文章詳情頁

java算法之靜態(tài)內(nèi)部類實現(xiàn)雪花算法

瀏覽:15日期:2022-08-12 18:56:40
目錄概述一、概念1、原理二、靜態(tài)類部類單例模式生產(chǎn)雪花ID代碼1、代碼2、測試結(jié)果3、為什么說41位時間戳最長只能有69年概述

在生成表主鍵ID時,我們可以考慮主鍵自增 或者 UUID,但它們都有很明顯的缺點

主鍵自增:1、自增ID容易被爬蟲遍歷數(shù)據(jù)。2、分表分庫會有ID沖突。

UUID: 1、太長,并且有索引碎片,索引多占用空間的問題 2、無序。

雪花算法就很適合在分布式場景下生成唯一ID,它既可以保證唯一又可以排序。為了提高生產(chǎn)雪花ID的效率,

在這里面數(shù)據(jù)的運算都采用的是位運算

一、概念1、原理

SnowFlake算法生成ID的結(jié)果是一個64bit大小的整數(shù),它的結(jié)構(gòu)如下圖:

java算法之靜態(tài)內(nèi)部類實現(xiàn)雪花算法

算法描述:

1bit 因為二進制中最高位是符號位,1表示負(fù)數(shù),0表示正數(shù)。生成的ID都是正整數(shù),所以最高位固定為0。

41bit-時間戳 精確到毫秒級,41位的長度可以使用69年。時間位還有一個很重要的作用是可以根據(jù)時間進行排序。

10bit-工作機器id 10位的機器標(biāo)識,10位的長度最多支持部署1024個節(jié)點。

12bit-序列號 序列號即一系列的自增id,可以支持同一節(jié)點同一毫秒生成多個ID序號。12位(bit)可以表示的最大正整數(shù)是java算法之靜態(tài)內(nèi)部類實現(xiàn)雪花算法,即可以用0、1、2、3、....4094這4095個數(shù)字,來表示同一機器同一時間截(毫秒)內(nèi)產(chǎn)生的4095個ID序號。

說明 由于在Java中64bit的整數(shù)是long類型,所以在Java中SnowFlake算法生成的id就是long來存儲的。

二、靜態(tài)類部類單例模式生產(chǎn)雪花ID代碼

下面生成雪花ID的代碼可以用于線上分布式項目中來生成分布式主鍵ID,因為設(shè)計采用的靜態(tài)內(nèi)部類的單例模式,通過加synchronized鎖來保證在

同一個服務(wù)器線程安全。至于不同服務(wù)器其實是不相關(guān)的,因為它們的機器碼是不一致的,所以就算同一時刻兩臺服務(wù)器都產(chǎn)生了雪花ID,那也不會一樣的。

1、代碼

public class SnowIdUtils { /** * 私有的 靜態(tài)內(nèi)部類 */ private static class SnowFlake {/** * 內(nèi)部類對象(單例模式) */private static final SnowIdUtils.SnowFlake SNOW_FLAKE = new SnowIdUtils.SnowFlake();/** * 起始的時間戳 */private final long START_TIMESTAMP = 1557489395327L;/** * 序列號占用位數(shù) */private final long SEQUENCE_BIT = 12;/** * 機器標(biāo)識占用位數(shù) */private final long MACHINE_BIT = 10;/** * 時間戳位移位數(shù) */private final long TIMESTAMP_LEFT = SEQUENCE_BIT + MACHINE_BIT;/** * 最大序列號 (4095) */private final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);/** * 最大機器編號 (1023) */private final long MAX_MACHINE_ID = ~(-1L << MACHINE_BIT);/** * 生成id機器標(biāo)識部分 */private long machineIdPart;/** * 序列號 */private long sequence = 0L;/** * 上一次時間戳 */private long lastStamp = -1L;/** * 構(gòu)造函數(shù)初始化機器編碼 */private SnowFlake() { //模擬這里獲得本機機器編碼 long localIp = 4321; //localIp & MAX_MACHINE_ID最大不會超過1023,在左位移12位 machineIdPart = (localIp & MAX_MACHINE_ID) << SEQUENCE_BIT;}/** * 獲取雪花ID */public synchronized long nextId() { long currentStamp = timeGen(); //避免機器時鐘回?fù)? while (currentStamp < lastStamp) {// //服務(wù)器時鐘被調(diào)整了,ID生成器停止服務(wù).throw new RuntimeException(String.format('時鐘已經(jīng)回?fù)? Refusing to generate id for %d milliseconds', lastStamp - currentStamp)); } if (currentStamp == lastStamp) {// 每次+1sequence = (sequence + 1) & MAX_SEQUENCE;// 毫秒內(nèi)序列溢出if (sequence == 0) { // 阻塞到下一個毫秒,獲得新的時間戳 currentStamp = getNextMill();} } else {//不同毫秒內(nèi),序列號置0sequence = 0L; } lastStamp = currentStamp; //時間戳部分+機器標(biāo)識部分+序列號部分 return (currentStamp - START_TIMESTAMP) << TIMESTAMP_LEFT | machineIdPart | sequence;}/** * 阻塞到下一個毫秒,直到獲得新的時間戳 */private long getNextMill() { long mill = timeGen(); // while (mill <= lastStamp) {mill = timeGen(); } return mill;}/** * 返回以毫秒為單位的當(dāng)前時間 */protected long timeGen() { return System.currentTimeMillis();} } /** * 獲取long類型雪花ID */ public static long uniqueLong() {return SnowIdUtils.SnowFlake.SNOW_FLAKE.nextId(); } /** * 獲取String類型雪花ID */ public static String uniqueLongHex() {return String.format('%016x', uniqueLong()); } /** * 測試 */ public static void main(String[] args) throws InterruptedException {//計時開始時間long start = System.currentTimeMillis();//讓100個線程同時進行final CountDownLatch latch = new CountDownLatch(100);//判斷生成的20萬條記錄是否有重復(fù)記錄final Map<Long, Integer> map = new ConcurrentHashMap();for (int i = 0; i < 100; i++) { //創(chuàng)建100個線程 new Thread(() -> {for (int s = 0; s < 2000; s++) { long snowID = SnowIdUtils.uniqueLong(); log.info('生成雪花ID={}',snowID); Integer put = map.put(snowID, 1); if (put != null) {throw new RuntimeException('主鍵重復(fù)'); }}latch.countDown(); }).start();}//讓上面100個線程執(zhí)行結(jié)束后,在走下面輸出信息latch.await();log.info('生成20萬條雪花ID總用時={}', System.currentTimeMillis() - start); }}2、測試結(jié)果

java算法之靜態(tài)內(nèi)部類實現(xiàn)雪花算法

從圖中我們可以得出

1、在100個線程并發(fā)下,生成20萬條雪花ID的時間大概在1.6秒左右,所有所性能還是蠻ok的。

2、生成20萬條雪花ID并沒有一條相同的ID,因為有一條就會拋出異常了。

3、為什么說41位時間戳最長只能有69年

我們思考41的二進制,最大值也就41位都是1,也就是也就是說41位可以表示java算法之靜態(tài)內(nèi)部類實現(xiàn)雪花算法

所以說雪花算法生成的ID,只能保證69年內(nèi)不會重復(fù),如果超過69年的話,那就考慮換個服務(wù)器部署吧,并且要保證該服務(wù)器的ID和之前都沒有重復(fù)過。

以上就是java算法之靜態(tài)內(nèi)部類實現(xiàn)雪花算法的詳細(xì)內(nèi)容,更多關(guān)于java算法的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 成人香蕉xxxxxxx | 国产精品视频一区二区猎奇 | 九九九九热精品视频 | 久久99国产精一区二区三区! | 免费观看成年人网站 | 日本黄页网站在线观看 | 国产精品高清在线 | 亚洲欧美综合一区二区三区四区 | 又黄又湿又爽吸乳视频 | 日韩精品一区二区三区 在线观看 | 毛片免费在线播放 | 一级欧美过瘾大片 | 国产精品第五页 | 亚洲精品15p | 最新怡红院全部视频在线 | 一区二区成人国产精品 | 香蕉久久一区二区不卡无毒影院 | 91免费国产高清观看 | 一区二区三区中文字幕 | 9999视频| 亚洲精品在线免费 | 国产成人亚洲毛片 | 久久成年片色大黄全免费网站 | 国产成人精品微拍视频 | 久久久久毛片免费观看 | 精品一区二区三区的国产在线观看 | 99久久99久久精品免费看子 | 国产大乳孕妇喷奶水在线观看 | 久久www免费人成看国产片 | 欧美国产91 | 手机看片国产免费久久网 | 亚洲综合久 | 免费看欧美一级特黄a大片一 | 丁香伊人五月综合激激激 | 97视频免费上传播放 | 日韩精品福利视频一区二区三区 | 亚洲日本aⅴ片在线观看香蕉 | 狠狠综合久久久久综合小说网 | 黄色福利网 | 老司机午夜精品网站在线观看 | 欧美最猛性xxxxx亚洲精品 |