国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

生成12位短id,自增且不連續(xù),永不重復(fù),不依賴(lài)數(shù)據(jù)庫(kù)

這篇具有很好參考價(jià)值的文章主要介紹了生成12位短id,自增且不連續(xù),永不重復(fù),不依賴(lài)數(shù)據(jù)庫(kù)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

基本思路:

設(shè)計(jì)模式:?jiǎn)卫J?/p>

是否加鎖:是 synchronized

獲取最后一次生成的時(shí)間戳值T0

限定初始時(shí)間為2023-08-01 00:00:00,獲取當(dāng)前時(shí)間時(shí)間戳T1,T1與初始時(shí)間的毫秒差值T2,轉(zhuǎn)為16進(jìn)制,轉(zhuǎn)為字符串為r1,獲取該字符串的長(zhǎng)度L1

獲取L2 (length - L1) ,獲取L2位數(shù)字的16進(jìn)制自增數(shù)值范圍,取最大值max

現(xiàn)數(shù)據(jù)庫(kù)批量導(dǎo)入數(shù)據(jù)速度為 n條/ms

平均步長(zhǎng)為max/n,(0~平均步長(zhǎng))的平均數(shù)為max/n/2,假設(shè)使用平均步長(zhǎng)最為隨機(jī)步長(zhǎng)范圍,最終的值與max相差較遠(yuǎn),大約后一半的數(shù)字沒(méi)有被使用

將平均步長(zhǎng)*2-平均步長(zhǎng)*容錯(cuò)因子(0.1)的值作為我們隨機(jī)步長(zhǎng)的范圍 ?容錯(cuò)因子:減小溢出概率

隨機(jī)步長(zhǎng)step = max/n*2 - max/n*0.1

獲取T1

如果T1 == T0,序列值seqNum = seqNum + step (轉(zhuǎn)為16進(jìn)制),若seqNum > max,該線(xiàn)程暫停1毫秒后刷新r1

如果T1 > T0,序列值seqNum = 0 + step

設(shè)置T0

代碼實(shí)現(xiàn)如下:

/**
 * 生成短id
 * @author mayu
 */
public class ShortIdWorker {

    /**
     * 初始時(shí)間限定為2023-08-01 00:00:00
     */
    private final static long START_STAMP = 1690819200000L;

    /**
     * 容錯(cuò)因子
     */
    private final static int FAULT_TOLERANCE_FACTOR = 10;

    /**
     * 默認(rèn)長(zhǎng)度
     */
    private final static int DEFAULT_ID_LENGTH = 12;

    /**
     * 數(shù)據(jù)庫(kù)每毫秒可保存的數(shù)據(jù),結(jié)合列的數(shù)量取值,建議實(shí)測(cè)后更改
     */
    private final static int DEFAULT_TRANSFER_SPEED_PER_MILLISECOND = 50;

    private final int length;

    private final int transferSpeedPerMillisecond;

    /**
     * 上次運(yùn)行時(shí)間
     */
    private long lastStamp = -1L;

    /**
     * 增長(zhǎng)序列
     */
    private int seqNum;

    private static ShortIdWorker instance;

    /**
     * 單例模式
     */
    public static ShortIdWorker getInstance() {
        if (null == instance) {
            instance = new ShortIdWorker();
        }
        return instance;
    }

    public static ShortIdWorker newInstance(int length, int transferSpeedPerMillisecond) {
        return new ShortIdWorker(length, transferSpeedPerMillisecond);
    }

    /**
     * 默認(rèn)使用12位id,數(shù)據(jù)庫(kù)每毫秒新增數(shù)據(jù)為50條
     */
    private ShortIdWorker() {
        this(DEFAULT_ID_LENGTH, DEFAULT_TRANSFER_SPEED_PER_MILLISECOND);
    }

    private ShortIdWorker(int length, int transferSpeedPerMillisecond) {
        this.length = length;
        this.transferSpeedPerMillisecond = transferSpeedPerMillisecond;
    }

    /**
     * @return 生成后的id
     * <p>
     * 例:757b12c001d3
     * 共length位id,前x位為時(shí)間戳差值的16進(jìn)制,后y位為不固定步長(zhǎng)的自增序列
     */
    public synchronized String nextId() {
        long now = now();
        // 獲取16進(jìn)制時(shí)間戳前綴
        String stampPrefix = getStampStr(now);
        // 獲取第二段增長(zhǎng)序列的長(zhǎng)度l2
        int l2 = this.length - stampPrefix.length();
        // 獲取l2位16進(jìn)制的最大值
        int max = IntStream.range(0, l2).map(i -> 16).reduce(1, (a, b) -> a * b) - 1;
        // 獲取增長(zhǎng)的平均步長(zhǎng)averageStepLength
        int averageStepLength = max / this.transferSpeedPerMillisecond;
        // 取步長(zhǎng)范圍
        // averageStepLength的平均值是averageStepLength/2,累加的情況下會(huì)有后一半的空間浪費(fèi)問(wèn)題,故取值為averageStepLength*2,平均值為averageStepLength
        // 取隨機(jī)數(shù)的結(jié)果不可控,上行中列舉的只是近似值,為防止多次溢出影響程序執(zhí)行時(shí)間,再減去容錯(cuò)因子,減小溢出概率(容錯(cuò)因子建議在本地系統(tǒng)實(shí)測(cè)后更改)
        int randomStepLengthMax = (averageStepLength << 1) - (averageStepLength / FAULT_TOLERANCE_FACTOR);
        // 在步長(zhǎng)范圍內(nèi)獲取隨機(jī)步長(zhǎng)
        int randomStepLength = new Random().nextInt(randomStepLengthMax) + 1;
        // 當(dāng)上次運(yùn)行時(shí)間小于當(dāng)前時(shí)間或第一次運(yùn)行時(shí),增長(zhǎng)序列賦值為隨機(jī)步長(zhǎng),設(shè)置最后運(yùn)行時(shí)間
        if (this.lastStamp < now || this.lastStamp == -1L) {
            this.seqNum = randomStepLength;
            this.lastStamp = now;
        // 當(dāng)上次運(yùn)行時(shí)間與當(dāng)前運(yùn)行時(shí)間處于同一毫秒時(shí)
        } else if (this.lastStamp == now) {
            // 增長(zhǎng)序列以隨機(jī)步長(zhǎng)為步長(zhǎng)遞增
            this.seqNum += randomStepLength;
            // 當(dāng)增長(zhǎng)序列大于最大值時(shí)
            if (this.seqNum > max) {
                // 程序暫停一毫秒
                LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1));
                // 重新獲取前綴,增長(zhǎng)序列重新開(kāi)始
                this.seqNum = randomStepLength;
                Long newNow = now();
                this.lastStamp = newNow;
                stampPrefix = getStampStr(newNow);
            }
        } else {
            // 時(shí)鐘回?fù)?,?bào)錯(cuò)
            throw new IllegalStateException("Clock moved backwards.  Reject to generate id");
        }
        // 將增長(zhǎng)序列轉(zhuǎn)為16進(jìn)制與時(shí)間戳拼接
        return stampPrefix + String.format("%0" + l2 + "X", new BigInteger(String.valueOf(this.seqNum), 10));
    }


    private String hex10To16(String str) {
        return String.format("%X", new BigInteger(str, 10));
    }

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

    /**
     * 獲取傳入時(shí)間與開(kāi)始時(shí)間的間隔毫秒數(shù),將結(jié)果轉(zhuǎn)為16進(jìn)制
     * @param now 時(shí)間戳
     * @return
     */
    private String getStampStr(Long now) {
        return hex10To16(String.valueOf(now - START_STAMP));
    }

????????8位16進(jìn)制可使用到4201年-03-20 07:32:15,后續(xù)時(shí)間戳所占位數(shù)自動(dòng)變?yōu)?位,id總長(zhǎng)度不變,不用擔(dān)心id用盡的問(wèn)題。

????????代碼中關(guān)于時(shí)間賦值的代碼請(qǐng)謹(jǐn)慎改動(dòng),順序顛倒會(huì)產(chǎn)生bug。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-682609.html

到了這里,關(guān)于生成12位短id,自增且不連續(xù),永不重復(fù),不依賴(lài)數(shù)據(jù)庫(kù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Linux命令:重復(fù)多次后臺(tái)運(yùn)行且不保存輸出,查看命令對(duì)應(yīng)的進(jìn)程數(shù)量

    要在后臺(tái)重復(fù)運(yùn)行 Linux 命令并查看對(duì)應(yīng)的進(jìn)程數(shù)量,你可以使用循環(huán)結(jié)構(gòu)和后臺(tái)運(yùn)行符號(hào) `` 結(jié)合起來(lái)。以下是一個(gè)示例: ```bash for i in {1..3}; do ? ? your_command /dev/null 21 done ``` 命令 `your_command /dev/null 21 ` 的含義如下: 1. `` 符號(hào)表示重定向輸出。在這個(gè)命令中,`your_command` 的標(biāo)

    2024年02月22日
    瀏覽(29)
  • 【數(shù)據(jù)庫(kù)】自增ID有什么壞處?什么樣的場(chǎng)景下不使用自增ID?

    在MySQL中,數(shù)據(jù)表的主鍵一般采用id字段自增的形式。使用自增ID給我們帶來(lái)不少便捷,但也有不少壞處,在一些場(chǎng)景下是不推薦使用自增ID的。 自增ID是在設(shè)計(jì)表時(shí)將id字段的值設(shè)置為自增的形式,這樣當(dāng)插入一行數(shù)據(jù)時(shí)無(wú)需指定id會(huì)自動(dòng)根據(jù)前一字段的ID值+1進(jìn)行填充。在My

    2024年02月07日
    瀏覽(21)
  • postgresql設(shè)置id自增

    創(chuàng)建序列: 將序列與表的列關(guān)聯(lián): 可選地,你可以設(shè)置序列的起始值、遞增步長(zhǎng)和最大值: 完成上述步驟后,每次向表中插入新記錄時(shí),ID 列都會(huì)自動(dòng)遞增。可以使用以下命令查看當(dāng)前序列的值: 這就是在 PostgreSQL 中將 ID 進(jìn)行遞增的基本方法。

    2024年02月03日
    瀏覽(31)
  • 表id自增的方法

    表id自增的方法

    數(shù)據(jù)庫(kù)主鍵id自增的方法,列舉了幾種如下 一、數(shù)據(jù)庫(kù)自增 (部分?jǐn)?shù)據(jù)庫(kù)支持) 創(chuàng)建表的時(shí)候設(shè)置id自增即可,或者后期修改表id自增 二、序列號(hào) (適合oracle) 三、mybatis獲取自增 (通用) sql語(yǔ)句被執(zhí)行的時(shí)候會(huì)自動(dòng)帶上主鍵字段和填充值去執(zhí)行,語(yǔ)句中就不用寫(xiě)id字段了

    2024年02月08日
    瀏覽(14)
  • hive創(chuàng)建唯一標(biāo)識(shí)列(自增id)

    目錄 一、需求 二、方法 1.row_number() 2.UUID 3.row_sequence() 三、對(duì)比 在某一張 hive 表中需要有一列去唯一標(biāo)識(shí)某一行,有些類(lèi)似于MySQL中的自增ID 使用UDF函數(shù)row_sequence(),必須在Hive環(huán)境要有hive-contrib相關(guān)jar包 執(zhí)行查詢(xún)語(yǔ)句 row_number函數(shù)是對(duì)整個(gè)數(shù)據(jù)集做處理,自增序列在當(dāng)次排序

    2024年02月14日
    瀏覽(25)
  • Navicat Premium創(chuàng)建表設(shè)置id自增

    Navicat Premium創(chuàng)建表設(shè)置id自增

    我們?cè)谑褂肗avicat Premium的時(shí)候創(chuàng)建表時(shí)左下角沒(méi)有id自增選項(xiàng)的 那怎么才能實(shí)現(xiàn)id自增呢 ? ?nextval(\\\'tooksto\\\'::regclass)

    2024年02月15日
    瀏覽(23)
  • sqlite插入語(yǔ)句id自增列問(wèn)題

    sqlite給主鍵id設(shè)置AUTOINCREMENT自增在插入數(shù)據(jù)的時(shí)候報(bào)錯(cuò)table has x?columns but x-1 values were supplied 為什么自增列要顯示不提供,sqlite需要提供自增列table ResTools has 7 columns but 6 values were supplied SQL Statement:insert into ResTools values(\\\'管理系統(tǒng)winform+Sqlite\\\',\\\'項(xiàng)目\\\\C#程序設(shè)計(jì)\\\\C#winform項(xiàng)目\\\\管理系

    2024年01月18日
    瀏覽(21)
  • 使用hive sql 為hive增加或者創(chuàng)建自增列,自增id的五種方式

    使用hive sql 為hive增加或者創(chuàng)建自增列,自增id的五種方式

    *注意:此篇完全是廢話(huà),是錯(cuò)誤演示文檔 創(chuàng)建帶有自增ID的Hive表的方法是使用Hive中的 SERDE (序列化和反序列化)和 ROW FORMAT 來(lái)為表添加自增ID。具體步驟如下: 在上面的代碼中,我們首先使用 CREATE TABLE 語(yǔ)句創(chuàng)建一個(gè)名為 your_table 的表,并指定了表的列和數(shù)據(jù)類(lèi)型。

    2023年04月18日
    瀏覽(21)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包