首頁 >php框架 >Laravel >Laravel 分散式唯一 ID 產生器使用

Laravel 分散式唯一 ID 產生器使用

Guanhui
Guanhui轉載
2020-06-17 17:20:545308瀏覽

Laravel 分散式唯一 ID 產生器使用

在應用程式中,經常需要全域唯一的ID作為資料庫主鍵。如何產生全域唯一ID?

首先,要確定全域唯一ID是整數還是字串?如果是字串,那麼現有的UUID就完全滿足需求,不需要額外的工作。缺點是字串作為ID佔用空間大,索引效率比整數低。

如果採用整數作為ID,那麼先排除掉32位元int型別,因為範圍太小,必須使用64位元long型。

採用整數作為ID時,如何產生自增、全域唯一且不重複的ID?

方案一:利用資料庫的自增ID,從1開始,基本上可以做到連續遞增。 Oracle可以用SEQUENCE,MySQL可以用主鍵的AUTO_INCREMENT,雖然無法保證全域唯一,但每個表唯一,也基本上滿足需求。

資料庫自增ID的缺點是資料在插入前,無法取得ID。資料插入後,取得的ID雖然是唯一的,但一定要等到事務提交後,ID才算是有效的。有些雙向引用的數據,只好插入後再做一次更新,比較麻煩。

第二種方式是採用一個集中式ID產生器,它可以是Redis,也可以是ZooKeeper,也可以利用資料庫的表記錄最後分配的ID。

這種方式最大的缺點是複雜性太高,需要嚴重依賴第三方服務,而且程式碼配置繁瑣。一般來說,越是複雜的方案,越不可靠,而且測試越痛苦。

第三種方式是類似Twitter的Snowflake演算法,它給每台機器一個唯一標識,然後透過時間戳記 標識 自增實現全域唯一ID。這種方式好處在於ID生成演算法完全是無狀態機,無網路調用,高效可靠。缺點是如果唯一識別有重複,會造成ID衝突。

Snowflake演算法採用41bit毫秒時間戳,加上10bit機器ID,加上12bit序號,理論上最多支援1024台機器每秒產生4096000個序號,對於Twitter的規模來說夠用了。

但是對於絕大部分普通應用程式來說,根本不需要每秒超過400萬的ID,機器數量也達不到1024台,所以,我們可以改進一下,使用更短的ID生成方式:

53bitID由32bit秒時間戳記16bit自增5bit機器標識組成,累積32台機器,每秒可產生6.5萬個序號,核心代碼:

private static synchronized long nextId(long epochSecond) {
    if (epochSecond < lastEpoch) {
        // warning: clock is turn back:
        logger.warn("clock is back: " + epochSecond + " from previous:" + lastEpoch);
        epochSecond = lastEpoch;
    }
    if (lastEpoch != epochSecond) {
        lastEpoch = epochSecond;
        reset();
    }
    offset++;
    long next = offset & MAX_NEXT;
    if (next == 0) {
        logger.warn("maximum id reached in 1 second in epoch: " + epochSecond);
        return nextId(epochSecond + 1);
    }
    return generateId(epochSecond, next, SHARD_ID);}

時間戳減去一個固定值,此方案最高可支援到2106年。

如果每秒6.5萬個序號不夠怎麼辦?沒關係,可以繼續遞增時間戳,向前「借」下一秒的6.5萬個序號。

同時也解決了時間回撥的問題。

機器標識採用簡單的主機名稱方案,只要主機名稱符合host-1host-2就可以自動提取機器標識,無需配置。

最後,為什麼採用最多53位元整數,而不是64位元整數?這是因為考慮到大部分應用程式是Web應用,如果要和JavaScript打交道,由於JavaScript支援的最大整數就是53位,超過這個位數,JavaScript將會遺失精確度。因此,使用53位元整數可以直接由JavaScript讀取,而超過53位元時,就必須轉換成字串才能保證JavaScript處理正確,這會為API介面帶來額外的複雜度。這也是為什麼新浪微博的API介面會同時回傳ididstr的原因。

推薦教學:《PHP》《Laravel教學

以上是Laravel 分散式唯一 ID 產生器使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:learnku.com。如有侵權,請聯絡admin@php.cn刪除