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

【分布式】分布式ID

這篇具有很好參考價(jià)值的文章主要介紹了【分布式】分布式ID。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

前言

分布式場(chǎng)景下,一張表可能分散到多個(gè)數(shù)據(jù)結(jié)點(diǎn)上。因此需要一些分布式ID的解決方案。

分布式ID需要有幾個(gè)特點(diǎn):

  • 全局唯一(必要) :在多個(gè)庫(kù)的主鍵放在一起也不會(huì)重復(fù)
  • 有序(必要) :避免頻繁觸發(fā)索引重建
  • 信息安全:ID連續(xù),可以根據(jù)訂單編號(hào)計(jì)算一天的單量,造成信息泄露
  • 包含時(shí)間戳:能夠快速根據(jù)ID得知生成時(shí)間

下面幾種方案按推薦順序排序,越推薦使用越靠前。

一、雪花算法snowflake

64 位的 long 類(lèi)型的唯一 id
【分布式】分布式ID,# 分布式,分布式

1. 組成

1)1位不用

帶符號(hào)整數(shù)第1位是符號(hào)位,正數(shù)是0,ID一般為正數(shù),此位不用。

2)41位毫秒級(jí)時(shí)間戳

41位存儲(chǔ)當(dāng)前時(shí)間截 – 開(kāi)始時(shí)間截得到的差值,可以表示 2 41 2^{41} 241個(gè)毫秒的值,轉(zhuǎn)化成單位年則是: 2 41 1000 ? 60 ? 60 ? 24 ? 365 = 69 年 \frac{2^{41}}{1000?60?60?24?365}=69年 1000?60?60?24?365241?=69

注:開(kāi)始時(shí)間截由程序指定,一般是id生成器開(kāi)始使用的時(shí)間,設(shè)置好后避免更改。依賴(lài)服務(wù)器時(shí)間,服務(wù)器時(shí)鐘回?fù)軙r(shí)可能會(huì)生成重復(fù) id。

3)10位機(jī)器ID

生成ID的服務(wù)可以部署在1024臺(tái)機(jī)器上

4)12位序列號(hào)
能夠表示4096個(gè)序列號(hào)。

因此,某一毫秒,同一臺(tái)機(jī)器,最多能生成4096個(gè)序號(hào)。理論上單機(jī)QPS最大為4096*1000=409.6w/s

2. 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • ID不重復(fù):用時(shí)間戳+機(jī)器+序號(hào)生成不重復(fù)ID
  • 性能高:在內(nèi)存中生成
  • 有序

缺點(diǎn):

依賴(lài)服務(wù)器時(shí)間,存在時(shí)鐘回?fù)艿膯?wèn)題。

3. 時(shí)鐘回?fù)茉趺唇鉀Q

時(shí)鐘回?fù)芸赡墚a(chǎn)生重復(fù)ID進(jìn)而影響關(guān)聯(lián)系統(tǒng)。

a. 時(shí)鐘回?fù)?/h4>

什么是時(shí)鐘回?fù)埽?/strong> 服務(wù)器上的時(shí)間倒退回之前的時(shí)間

哪些情況造成時(shí)鐘回?fù)埽?/strong>

  • 人為修改服務(wù)器時(shí)間
  • 時(shí)鐘同步后,由于機(jī)器之間時(shí)間不同,可能產(chǎn)生時(shí)鐘回?fù)?/li>

b. 解決方案

算法中會(huì)記錄當(dāng)前服務(wù)上次生成ID的最后時(shí)間,只需要保證我下次生成ID的時(shí)間大于上次最后時(shí)間即可。根據(jù)回?fù)芎髸r(shí)間距離上次生成最后時(shí)間大小,可以有不同的解決方案。

  • 相差0~100ms :等待直至當(dāng)前時(shí)間超過(guò)上次最后生活時(shí)間
  • 相差100ms~1s:采用等待方式可能導(dǎo)致接口超時(shí)??梢杂涗浺焉蒊D的最大ID,在這個(gè)基礎(chǔ)上++。(預(yù)留擴(kuò)展位,在擴(kuò)展位上增加。回?fù)芎笥只負(fù)芸赡苡袉?wèn)題)
  • 相差1s~5s:采用最大ID增加的方式,時(shí)間過(guò)長(zhǎng)可能導(dǎo)致范圍溢出??梢陨蒊D服務(wù)響應(yīng)異常,由調(diào)用方例如基于Ribbon調(diào)用其他生成ID服務(wù)。
  • 相差超過(guò)5s:采用Ribbon循環(huán)調(diào)用的方式,下次訪(fǎng)問(wèn)到時(shí)鐘回?fù)艿姆?wù)可能還沒(méi)達(dá)到上次生成最后時(shí)間,浪費(fèi)時(shí)間??梢宰尦^(guò)5s的服務(wù)主動(dòng)下線(xiàn),并通知運(yùn)維,人工介入,等待時(shí)鐘正常后再重啟。

4. 項(xiàng)目中如何使用

【分布式】分布式ID,# 分布式,分布式

時(shí)鐘回?fù)艿奶幚磉壿嬙趎extId()里的if (timestamp < lastTimestamp) 邏輯下。這里直接拋出異常。

public class SnowflakeIdWorker {

    // ==============================Fields===========================================
    /** 開(kāi)始時(shí)間截 (2020-01-01) */
    private final long twepoch = 1577808000000L;

    /** 機(jī)器id所占的位數(shù) */
    private final long workerIdBits = 5L;

    /** 數(shù)據(jù)標(biāo)識(shí)id所占的位數(shù) */
    private final long datacenterIdBits = 5L;

    /** 支持的最大機(jī)器id,結(jié)果是31 (這個(gè)移位算法可以很快的計(jì)算出幾位二進(jìn)制數(shù)所能表示的最大十進(jìn)制數(shù)) */
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

    /** 支持的最大數(shù)據(jù)標(biāo)識(shí)id,結(jié)果是31 */
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

    /** 序列在id中占的位數(shù) */
    private final long sequenceBits = 12L;

    /** 機(jī)器ID向左移12位 */
    private final long workerIdShift = sequenceBits;

    /** 數(shù)據(jù)標(biāo)識(shí)id向左移17位(12+5) */
    private final long datacenterIdShift = sequenceBits + workerIdBits;

    /** 時(shí)間截向左移22位(5+5+12) */
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

    /** 生成序列的掩碼,這里為4095 (0b111111111111=0xfff=4095) */
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);

    /** 工作機(jī)器ID(0~31) */
    private long workerId;

    /** 數(shù)據(jù)中心ID(0~31) */
    private long datacenterId;

    /** 毫秒內(nèi)序列(0~4095) */
    private long sequence = 0L;

    /** 上次生成ID的時(shí)間截 */
    private long lastTimestamp = -1L;

    //==============================Constructors=====================================
    /**
     * 構(gòu)造函數(shù)
     * @param workerId 工作ID (0~31)
     * @param datacenterId 數(shù)據(jù)中心ID (0~31)
     */
    public  SnowflakeIdWorker(long workerId, long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }

    // ==============================Methods==========================================
    /**
     * 獲得下一個(gè)ID (該方法是線(xiàn)程安全的)
     * @return SnowflakeId
     */
    public synchronized long nextId() {
        long timestamp = timeGen();

        //如果當(dāng)前時(shí)間小于上一次ID生成的時(shí)間戳,說(shuō)明系統(tǒng)時(shí)鐘回退過(guò)這個(gè)時(shí)候應(yīng)當(dāng)拋出異常
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(
                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        //如果是同一時(shí)間生成的,則進(jìn)行毫秒內(nèi)序列
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            //毫秒內(nèi)序列溢出
            if (sequence == 0) {
                //阻塞到下一個(gè)毫秒,獲得新的時(shí)間戳
                timestamp = tilNextMillis(lastTimestamp);
            }
        }
        //時(shí)間戳改變,毫秒內(nèi)序列重置
        else {
            sequence = 0L;
        }

        //上次生成ID的時(shí)間截
        lastTimestamp = timestamp;

        //移位并通過(guò)或運(yùn)算拼到一起組成64位的ID
        return ((timestamp - twepoch) << timestampLeftShift) //
                | (datacenterId << datacenterIdShift) //
                | (workerId << workerIdShift) //
                | sequence;
    }

    /**
     * 阻塞到下一個(gè)毫秒,直到獲得新的時(shí)間戳
     * @param lastTimestamp 上次生成ID的時(shí)間截
     * @return 當(dāng)前時(shí)間戳
     */
    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    /**
     * 返回以毫秒為單位的當(dāng)前時(shí)間
     * @return 當(dāng)前時(shí)間(毫秒)
     */
    protected long timeGen() {
        return System.currentTimeMillis();
    }

    //==============================Test=============================================
    /** 測(cè)試 */
    public static void main(String[] args) {
        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);

        for (int i = 0; i < 100; i++) {
            long id = idWorker.nextId();
            System.out.println(id);
        }
    }
}

二、基于Redis

三、基于Zookeeper

四、號(hào)段模式

數(shù)據(jù)庫(kù)中保存號(hào)段表,每次從數(shù)據(jù)庫(kù)獲取一個(gè)號(hào)段范圍,由服務(wù)在內(nèi)存中自增生成ID,直到達(dá)到號(hào)段范圍再去獲取。

id 業(yè)務(wù)類(lèi)型 最大可用ID 號(hào)段長(zhǎng)度 版本號(hào)
1 xxx 2000 1000 0
updateset 最大可用ID = 3000, version = version + 1 where version = 0 and biz_type = xxx

采用樂(lè)觀(guān)鎖的方式避免長(zhǎng)時(shí)間鎖表。

優(yōu)點(diǎn):

  • ID有序遞增
  • 對(duì)數(shù)據(jù)庫(kù)壓力比較小

缺點(diǎn):

  • 存在安全問(wèn)題,用ID可以判斷數(shù)據(jù)量
  • 存在單點(diǎn)問(wèn)題,集群實(shí)現(xiàn)困難

五、指定步長(zhǎng)的自增ID

多主集群模式下,表主鍵設(shè)置自增ID,多節(jié)點(diǎn)之間會(huì)有重復(fù)ID。需要采用指定初始值的自增步長(zhǎng)
舉例:兩臺(tái)數(shù)據(jù)庫(kù)A,B。A初始值和步長(zhǎng)為(1,2),B初始值和步長(zhǎng)為(2,2)。兩張表生成的主鍵分別為
A:1,3,5,7…
B:2,4,6,8…

設(shè)置方法:

set @@auto_increment_offset = 1;     -- 起始值
set @@auto_increment_increment = 2;  -- 步長(zhǎng)

優(yōu)點(diǎn):

  • 簡(jiǎn)單、解決單點(diǎn)問(wèn)題

缺點(diǎn):

  • 擴(kuò)容困難

六、UUID

128位長(zhǎng)的字符標(biāo)識(shí)串,由32個(gè)16進(jìn)制數(shù)字組成,用-連接,共36個(gè)字符。如:03425604-5462-11ee-80ad-80fa5b8732b1

生成算法與重復(fù)性:

  • 基于隨機(jī)數(shù):不重復(fù)
  • 基于MAC地址:不重復(fù)
  • 基于時(shí)間戳:可能重復(fù)

作為分布式ID的優(yōu)缺點(diǎn):

  • 優(yōu)點(diǎn):本地生成,性能高,無(wú)網(wǎng)絡(luò)損耗
  • 缺點(diǎn):
    • 無(wú)序:造成索引重建,入庫(kù)性能差
    • 字符串長(zhǎng):需要36字符

參考

  • UUID會(huì)重復(fù)嗎?
  • 雪花算法視頻
  • 9種分布式ID生成方式

六、擴(kuò)展

  • 百度:UidGenerator
  • 美團(tuán):Leaf

總結(jié)

優(yōu)點(diǎn) 缺點(diǎn)
uuid 實(shí)現(xiàn)簡(jiǎn)單 連續(xù)性差,作為主鍵每次新增數(shù)據(jù)都會(huì)觸發(fā)索引重建。
分布式環(huán)境中可能重復(fù)
雪花算法 性能好,有序 依賴(lài)服務(wù)器時(shí)間,時(shí)鐘回?fù)芸赡苌芍貜?fù)ID
號(hào)段模式
redis/zookeeper Redis基于INCR 命令生成 分布式全局唯一id
zookeeper一種通過(guò)節(jié)點(diǎn),一種通過(guò)節(jié)點(diǎn)的版本號(hào)

基因算法文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-731866.html

到了這里,關(guān)于【分布式】分布式ID的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀(guān)點(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)文章

  • 架構(gòu)設(shè)計(jì)-分布式ID

    架構(gòu)設(shè)計(jì)-分布式ID

    1.不要用主鍵ID作為業(yè)務(wù)單號(hào)的唯一標(biāo)識(shí),因?yàn)橐皇菙?shù)據(jù)同步麻煩,第二一旦業(yè)務(wù)數(shù)據(jù)擴(kuò)張涉及到分庫(kù)分表則數(shù)據(jù)維護(hù)麻煩,因?yàn)榇藭r(shí)主鍵ID容易造成重復(fù) 。 2.對(duì)于有相似屬性的業(yè)務(wù)ID如直播或者錄播ID存儲(chǔ)在業(yè)務(wù)表中的一個(gè)字段,一旦程序員哪天狀態(tài)不好忘記區(qū)分類(lèi)型,就很

    2024年02月03日
    瀏覽(20)
  • 算法、語(yǔ)言混編、分布式鎖與分布式ID、IO模型

    算法、語(yǔ)言混編、分布式鎖與分布式ID、IO模型

    數(shù)據(jù)結(jié)構(gòu)和算法是程序的基石。我們使用的所有數(shù)據(jù)類(lèi)型就是一種數(shù)據(jù)結(jié)構(gòu)(數(shù)據(jù)的組織形式),寫(xiě)的程序邏輯就是算法。 算法是指用來(lái)操作數(shù)據(jù)、解決程序問(wèn)題的一組方法。 對(duì)于同一個(gè)問(wèn)題,使用不同的算法,也許最終得到的結(jié)果是一樣的,但在過(guò)程中消耗的資源(空間

    2024年02月08日
    瀏覽(21)
  • 分布式ID系統(tǒng)設(shè)計(jì)(3)

    第二集說(shuō)了id-service-Segment-DB可以生成趨勢(shì)遞增的ID,但是ID號(hào)是可以計(jì)算的。不太適用于一些訂單ID生成的場(chǎng)景。因?yàn)榇嬖跀?shù)據(jù)暴露的風(fēng)險(xiǎn) 比如我可以對(duì)比兩天的訂單ID號(hào)來(lái)大致計(jì)算出公司一天的訂單量。這個(gè)有點(diǎn)危險(xiǎn)。 所以我們需要id-serviceSnowFlake方案。 id-service-snowFlake完全沿

    2024年02月06日
    瀏覽(24)
  • 分布式ID系統(tǒng)設(shè)計(jì)(1)

    我們姑且把它叫做id-server 。那么這么個(gè)id-server的設(shè)計(jì)和考慮需要什么 全局唯一:不能出現(xiàn)重復(fù)的id號(hào) 最基本要求。 趨勢(shì)遞增: 在innodb中使用的是聚集索引。B+Tree的pk最好是有序的 單調(diào)遞增:保證下一個(gè)id一定要大于上一個(gè)id 安全:如果ID是連續(xù)的 被爬蟲(chóng)的可能性能就很大。有一些

    2024年02月08日
    瀏覽(28)
  • 分布式ID系統(tǒng)設(shè)計(jì)(2)

    https://editor.csdn.net/md/?articleId=133988963 應(yīng)用舉例 mongoDB ObjectID 就是一個(gè)典型的實(shí)現(xiàn)。 以MySQL舉例 利用給字段設(shè)置AUTO-INCREMENT來(lái)保證ID自增,每次業(yè)務(wù)使用SQL拿到MySQL的ID 這種方案的優(yōu)缺點(diǎn): 優(yōu)點(diǎn) 1 簡(jiǎn)單。利用數(shù)據(jù)庫(kù)實(shí)現(xiàn) 成本小,有專(zhuān)業(yè)的DBA維護(hù) 2 ID單調(diào)遞增。用來(lái)實(shí)現(xiàn)一些對(duì)于ID有

    2024年02月06日
    瀏覽(26)
  • 分布式—雪花算法生成ID

    分布式—雪花算法生成ID

    由64個(gè)Bit(比特)位組成的long類(lèi)型的數(shù)字 0 | 0000000000 0000000000 0000000000 000000000 | 00000 | 00000 | 000000000000 1個(gè)bit:符號(hào)位,始終為0。 41個(gè)bit:時(shí)間戳,精確到毫秒級(jí)別,可以使用69年。 10個(gè)bit:工作機(jī)器ID,可以部署在1024個(gè)節(jié)點(diǎn)上。 12個(gè)bit:序列號(hào),每個(gè)節(jié)點(diǎn)每毫秒內(nèi)最多可以生成

    2024年02月11日
    瀏覽(20)
  • MongoDB的分布式ID

    MongoDB ObjectID是MongoDB數(shù)據(jù)庫(kù)中的一種數(shù)據(jù)類(lèi)型,用于表示一個(gè)文檔(document)在集合(collection)中的唯一標(biāo)識(shí)符。每個(gè)ObjectID值是一個(gè)12字節(jié)的字符串,其中前四個(gè)字節(jié)表示時(shí)間戳,后三個(gè)字節(jié)表示機(jī)器編號(hào),后兩個(gè)字節(jié)表示進(jìn)程編號(hào),最后一個(gè)字節(jié)表示隨機(jī)數(shù)。由于MongoDB O

    2024年02月16日
    瀏覽(27)
  • 76、分布式id生成方案

    1,當(dāng)前日期和時(shí)間 時(shí)間戳 2,時(shí)鐘序列。 計(jì)數(shù)器 3,全局唯一的IEEE機(jī)器識(shí)別號(hào),如果有網(wǎng)卡,從網(wǎng)卡MAC地址獲得,沒(méi)有網(wǎng)卡以其他方式獲得。 優(yōu)點(diǎn): 代碼簡(jiǎn)單,性能好(本地生成,沒(méi)有網(wǎng)絡(luò)消耗),保證唯一(相對(duì)而言,重復(fù)概率極低可以忽略) 缺點(diǎn): 每次生成的ID都是無(wú)序的,

    2024年02月16日
    瀏覽(20)
  • 分布式唯一ID 雪花算法

    分布式唯一ID 雪花算法

    ?????????個(gè)人主頁(yè):五敷有你? ? ?? ???系列專(zhuān)欄:算法分析與設(shè)計(jì) ??穩(wěn)中求進(jìn),曬太陽(yáng) 雪花算法是 64 位 的二進(jìn)制,一共包含了四部分: 1位是符號(hào)位,也就是最高位,始終是0,沒(méi)有任何意義,因?yàn)橐俏ㄒ挥?jì)算機(jī)二進(jìn)制補(bǔ)碼中就是負(fù)數(shù),0才是正數(shù)。 41位是時(shí)間戳

    2024年04月10日
    瀏覽(24)
  • 76.Go分布式ID總覽

    76.Go分布式ID總覽

    在分布式系統(tǒng)中,生成唯一的 ID 是一個(gè)核心問(wèn)題,特別是在需要確保數(shù)據(jù)完整性和避免沖突的場(chǎng)景中,比如作為鏈路追蹤的 trace_id ,作為冪等性的主鍵 id , 分布式鎖中為了避免釋放的是別人的鎖時(shí),本地保存的唯一 id 等。以下是對(duì)一些分布式唯一 ID 生成方法的詳細(xì)闡述,包

    2024年01月25日
    瀏覽(24)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包