深度解讀UUID:結構、原理以及生成機制

来源:https://www.cnblogs.com/cloud-/p/18086034
-Advertisement-
Play Games

專註探討UUID的核心原理及其生成機制,並詳細介紹不同版本UUID(如版本1的時間戳+節點ID、版本4的隨機數生成等)背後的數學原理和技術細節。 ...


What 是 UUID

UUID (Universally Unique IDentifier) 通用唯一識別碼 ,也稱為 GUID (Globally Unique IDentifier) 全球唯一標識符。

UUID是一個長度為128位的標誌符,能夠在時間和空間上確保其唯一性。UUID最初應用於Apollo網路計算系統,隨後在Open Software Foundation(OSF)的分散式計算環境(DCE)中得到應用。可讓分散式系統可以不藉助中心節點,就可以生成唯一標識, 比如唯一的ID進行日誌記錄。

並被微軟Windows平臺採用。
Windows 舉例2個使用場景:

  • COM組件通過GUID 來定義類標識符(CLSID)、介面標識符(IID)以及其他重要的標識,確保在整個系統中不會發生命名衝突。

截圖_20242927042948.png

  • Windows註冊表中很多項都使用GUID作為子鍵名,以便為特定程式或功能提供一個全球唯一的註冊表路徑。
    截圖_20242427042408.png

UUID之所以被廣泛採用,主要原因之一是它們的分配不需要中心管理機構介入。其具有唯一性和持久性,它們非常適合用作統一資源名稱(URN)。UUID能夠無需註冊過程就能生成新的標識符的獨特優點,使得UUID成為創建成本最低的URN類型之一。

那麼UUID會重覆嘛,由於UUID具有固定的大小並包含時間欄位,在特定演算法下,隨著時間推移,理論上在大約公元3400年左右會出現值的迴圈,所以問題不大。

由於UUID是一個128位的長的標誌符,為了便於閱讀和顯示,通常會將這個大整數轉換成32(不包含連接符)個十六進位字元組成的字元串形式。如下

crypto.randomUUID()
// 4d93f326-3f48-4a43-929d-b6489f4754b5

`${crypto.randomUUID()}`.length 
// 長度:36

`${crypto.randomUUID()}`.replace(/-/g, '').length
// 去掉連接符:32

這128位的組成,以及是怎麼變成32位的十六進位字元的,繼續往下看:

UUID 的結構

UUID看似雜亂無章,其實內有乾坤,慢慢道來。

必須瞭解的

  • 比特(bit):二進位數字系統中的基本單位。一個比特可以代表二進位中的一個0或1。
  • 位(通常情況下與比特同義):二進位數系統中的一位,同樣表示0或1。
  • 位元組(Byte):位元組是電腦中更常用的單位,用於衡量數據存儲容量和傳輸速率。1位元組等於8個比特。

總結起來就是:

  • 1 位元組 = 8 位
  • 1 位 = 1 比特

128位轉為32個十六進位字元, 這個十六進位字元是什麼呢,其專業名字為hexDigit,是UUID中我們肉眼可見的最小單元。

hexDigit

hexDigit , 十六進位數字字元,是一個長度為4比特,可以表示0(0b000)到15(0b1111)之間數值。其能轉為16進位的相對應符號,其取值範圍為 0-9,a-f, A-F, 即0123456789abcdefABCDEF某一個值。

所以, hexDigit 可以粗暴的理解為 0123456789abcdefABCDEF某一個值

 (0b1000).toString(16)     // 8
 (0b1111).toString(16)     // F

此外,還有一個hexOctet, 兩個連續hexDigit組成的序列, 占8個比特,即一個位元組。

UUID基本結構

在協議 RFC 4122: A Universally Unique IDentifier (UUID) URN Namespace4.1.2. Layout and Byte Order 有結構圖:

截圖_20240822110809.png

這個圖有點小迷惑, 最上面的 0,1,2,3 不是表示位數,就是簡單的表示10位數的值,9之後就是 10, 11, 12等等。

這圖不太好理解,換一張手工畫的圖(UUID 10類型的V4版本):
10類型和V4版本後續會解釋

截圖_20242801062840.png

128比特,16個位元組即 16 hexOctet,就被如下瓜分了。

欄位 hexOctet(位元組) 位置 備註
time_low 4 0-3 時間戳 的低位部分
time_mid 2 4-5 時間戳的中間部分
time_hi_and_version 2 6-7 時間戳高位部分與 版本 欄位,其中12位代表時間戳的高12位,4位則用來標識UUID的版本號
clock_seq_hi_and_reserved 1 8 時鐘序列 高位與 保留位
clock_seq_low 1 9 時鐘序列低位
node 6 10-15 節點標識符,提供空間唯一性,通常基於MAC地址或隨機數生成,以確保全局範圍內的唯一性

要想完整理解這個 6 部分組成,必然要理解備註中被加粗的幾個概念。
保留位版本時間戳時鐘序列節點標誌符

類型(變體) 和保留位

UUID可以分為四種類型(變體),怎麼識別是哪種類型(變體呢),UUID有對應的Variant欄位去標記,可以參見協議的 4.1.1. Variant部分。

variant欄位位於UUID的第8個位元組clock_seq_hi_and_reserved 部分的第6-7位。

截圖_20243201063204.png

以外所有其他位的含義都是依據variant欄位中的比特位設置來解讀的。從這個意義上講,variant欄位更準確地說可以被稱作類型欄位;然而為了與歷史文檔相容,仍沿用“variant”這一術語。

下表列出了variant欄位可能的內容,其中字母"x"表示無關緊要或不關心的值:

  • Msb0(最高有效位0):此為最高位。
  • Msb1:次高位。
  • Msb2:第三高位。
Msb0 Msb1 Msb2 描述
0 x x 保留,用於NCS(Network Computing System)向後相容
1 0 x 此文檔中指定的variant變體
1 1 0 保留,用於微軟公司系統的向後相容
1 1 1 保留供未來定義

類型(變體)的標誌符可以是 2位也可是3位,本文圍繞的的是 RFC4122: A Universally Unique IDentifier (UUID) URN Namespace 類型(變體), 即上面表格的第二行,其第三高位 為 x,表示該值並無意義,所以該版本只需要
10 即可。

10開頭的 hexDigit 十六進位數字字元,其只有四個值。

0b1000   => 8
0b1001   => 9
0b1010   => a
0b1011   => b

用簡單的圖示表示,就是 下麵y的部分只會是這 四個值 8, 9, a, b其中的某個值。
xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx

簡單測一測,
截圖_20245301115341.png

所以呢,一個RFC4122版本的 UUID正宗不正宗,這麼驗證也是一種手段。

版本(子類型)

上面提到了UUID的類型(變體), 而這裡版本,可以理解為某個類型(變體)下的不同子類型。 當然本文討論的是 變體 10RFC4122 下的版本(子類型)。 UUID的類型(變體)有欄位標記,當然 這裡的版本也有。

即版本號time_hi_and_version 的第12至15位

截圖_20241701031754.png

V4版本如下:
截圖_20243301063311.png
一共有5個版本:

截圖_20241401121433.png

用簡單的圖示表示,就是 下麵V的部分只會是這 五個值 1234, 5其中的某個值。
xxxxxxxx-xxxx-V xxx-yxxx-xxxxxxxxxxxx

借用uuid 庫演示一下:
截圖_20242301122348.png

時間戳

先回顧一下兩張圖

image.png

image.png

第一張是UUID 各部分的組成,time_low ,time_mid, time_hi_and_version 包含了時間戳的不同部分。

第二張是UUID的五個版本,但是只有 V1 和 V2 提到了時間戳,也確實是這樣,除了V1和V2版本真正用了時間戳,其餘版本通過不同手段生成了數據填充了time_low ,time_mid, time_hi_and_version 這三個部分。

那這個時間戳 是 開發者們 常用的 Date.now() 這個時間戳嘛, 答案當然不是。

這裡的時間戳是一個60位長度的數值。對於UUID版本1和2,它通過協調世界時(UTC)表示,即從1582年10月15日0點0分0秒開始算起的100納秒間隔計數。

比如 2024年1月1日0時0分0秒,這個值時間戳怎麼算呢

const startOfUuidEpoch = new Date('1582-10-15T00:00:00.000Z');
const uuidTimestampFromDate = (date) => {
  // 直接計算給定日期距離UUID紀元開始的毫秒數
  const msSinceUuidEpoch = date.getTime() - startOfUuidEpoch.getTime();

  // 將毫秒轉換為100納秒的整數倍,  1 毫秒=1000000 納秒
  const uuidTimestampIn100Ns = Math.floor(msSinceUuidEpoch * 10000); // 每毫秒乘以10,000得到100納秒

  return uuidTimestampIn100Ns;
};

// 計算2024年1月1日對應的UUID V1版本時間戳
const targetDate = new Date('2024-01-01T00:00:00.000Z');
const uuidV1Timestamp = uuidTimestampFromDate(targetDate); 
// 139233600000000000

要保存為60位, 並劃分高位(12),中間(16),低位三部分(32)

uuidV1Timestamp.toString(2).padStart(60,'0')
// 000111101110101010000011100010110100110011001000000000000000


time-high     time-mid          time-low
000111101110 1010100000111000 10110100110011001000000000000000

在不具備UTC功能但擁有本地時間的系統中,只要在整個系統內保持一致,也可以使用本地時間替代UTC。然而,這種方法並不推薦,因為僅需要一個時區偏移量即可從本地時間生成UTC時間。

對於UUID版本3或5,時間戳是一個根據4.3 Algorithm for Creating a Name-Based UUID,由名稱構建的60位值, V3和V5 區別是在演算法上。

而對於UUID版本4,時間戳則是一個隨機或偽隨機生成的60位值,具體細節參見第4.4 Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers

小結一下,

  • 時間戳是即從1582年10月15日0點0分0秒開始算起的100納秒間隔計數,是一個60位值,被分為 高位,中間,低位三部分填充到UUID中。
  • 只有V1和V2 真正意義上用了時間戳
  • V3和V5 由名字構建而成的60位值
  • V4隨機或偽隨機生成的60位值

時鐘序列

時鐘序列(clock sequence)用於幫助避免因系統時間被設置回溯或節點ID發生變化時可能出現的重覆標識符。

舉個實例,手動把系統的時間設置為一個過去的時間,那麼就可能導致生成重覆的UUID.

協議考慮到了這點,就增加了時鐘序列,增加一個變數,讓結果不一樣,當然如果序列也是不變的,那麼還是可能重覆,所以這個時鐘序列也是會變化的。

如果系統時鐘被設置為向前的時間點之前,或者可能已經回溯(例如,在系統關機期間),並且UUID生成器無法確定在此期間沒有生成時間戳更大的UUID,則需要更改時鐘序列。若已知先前時鐘序列的值,可以直接遞增;否則應將其設置為一個隨機或高質量的偽隨機值。

同樣,當節點ID發生變化(比如因為網路適配器在不同機器間移動),將時鐘序列設置為隨機數可以最大限度地降低由於各機器之間微小時間設置差異導致重覆UUID的可能性。儘管理論上知道與變更後的節點ID關聯的時鐘序列值後可以直接遞增,但這種情況在實際操作中往往難以實現。

時鐘序列必須在其生命周期內首次初始化為隨機數,以減少跨系統間的關聯性。這提供了最大程度的保護,防止可能會快速在系統間遷移或切換的節點標識符產生問題。初始值不應與節點標識符相關聯。

同樣的,這個時間序列只在 V1和V2 是真的按照上面的規則或者約定來執行的。

對於UUID版本3或5,時鐘序列是一個由第4.3 Algorithm for Creating a Name-Based UUID節描述的名稱構建的14位值。

而對於UUID版本4,時鐘序列則是一個如第4.4 Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers節所述隨機或偽隨機生成的14位值。

節點標誌符

空間唯一節點標識符,用來確保即便在同一時間生成的UUID也能在特定網路或物理位置上保持唯一性。

對於UUID V1,這個節點標識符通常基於網路適配器的MAC地址或者在沒有硬體MAC地址可用時由系統自動生成一個偽隨機數。它的目的是反映生成UUID的設備在網路或物理空間中的唯一性,即使在相同的時序和時鐘序列條件下,不同的設備也會因為其獨特的節點標識符而產生不同的UUID。

在UUID V2中,雖然不常用,但節點標識符的概念同樣適用,用於標識系統的唯一性,只不過這裡的“空間”更多地指向組織結構或其他邏輯意義上的空間劃分。

總之,空間唯一節點標識符是為了保證在分散式系統環境下,即使時間戳相同的情況下也能生成唯一的UUID,以區分不同物理節點上的事件或資源。

對於UUID版本3或5: 節點欄位(48位)是根據第4.3節描述的方法,從一個名稱構造而來。
對於UUID版本4: 節點欄位(同樣是48位)是一個隨機或偽隨機生成的值。

小結

從V1和V2版本來看, UUID最後是想通過 時間和空間 上兩層手段保證其唯一性:

  • 時間: 時間戳 + 時鐘時序
  • 空間: 節點標誌符(比如MAC地址)

同時考慮了 類型(變體) 和 版本(子類型),即下麵這些組信息組成了UUID

  • 時間戳
  • 時鐘序列
  • 節點標誌符
  • 保留位:即類型(變體)信息
  • 版本:V1到V5

因為保留位和版本信息本身是固定的,是可以從最後的32位16進位字元是可以直接或者間接看到的。

再回顧這張圖,是不是比較清晰了

截圖_20242801062840.png

UUID 的 生成

協議中有具體描述V1, V3和V5, 以及V4的基本流程或者約束。

v4

瀏覽器和nodejs內置的了V4的生成函數, 而且其生成規則相對簡單。
對應著協議 4.4. Algorithms for Creating a UUID from Truly Random or Pseudo-Random Numbers

版本4的UUID旨在通過真正的隨機數或偽隨機數生成UUID。其生成演算法相對簡單,主要依賴於隨機性:

生成演算法步驟如下:

  1. 在UUID結構中的clock_seq_hi_and_reserved部分,將最高兩位有效位(即第6位和第7位)分別設置為0和1。
  2. 在UUID結構中的time_hi_and_version欄位,將最高四位有效位(即第12位至第15位)設置為來自第 4.1.3節 的4位版本號,對於版本4 UUID,這個版本號是固定的0100
  3. 將除了以上已設定的位之外的所有其他位設置為隨機(或偽隨機)選取的值。

不好理解,就看這張圖:

image.png

關於隨機性安全要求, 引用了BCP 106標準文檔,即 RFC 4086。RFC 4086是一份由IETF制定的最佳當前實踐(Best Current Practice, BCP)文檔,其標題為“Security Requirements for Randomness”,該文檔詳細闡述了在實現安全協議與系統時所需的隨機數生成器的要求和特性,確保生成的隨機數具有足夠的不可預測性和熵,能滿足各類安全應用,包括但不限於密碼學應用中的隨機性需求。

總之,生成版本4 UUID的過程中,首先對特定欄位的幾位進行固定設置以標明版本和時鐘序列特征,然後其餘所有位均通過隨機或偽隨機過程填充數值,以此確保生成的UUID具備全球唯一性和較強的隨機性。

至於v2怎麼生成,協議貌似沒有提到, v1 , v3 和 v5均有提到,這邊就直接翻譯過來,有興趣的可以看看大致邏輯。不敢興趣的直接跳到後續章節

V1

對應這協議 4.2.2. Generation Details ,按照以下步驟生成的:

  1. 確定時間戳和時鐘序列:遵循第 4.2.1 節描述的方法,獲取基於 UTC 的時間戳以及用於 UUID 的時鐘序列。
  2. 處理時間戳和時鐘序列:將時間戳視為一個 60 位無符號整數,時鐘序列視為一個 14 位無符號整數,並按順序編號每個欄位中的位,最低有效位從0開始計數。
  3. 設置時間低位欄位(time_low field):將其設置為時間戳的最低有效 32 位(位 0 到 31),保持相同的位權重順序。
  4. 設置時間中間欄位(time_mid field):將其設置為時間戳中的位 32 到 47,同樣保持位權重順序一致。
  5. 設置時間高位及版本欄位(time_hi_and_version field)的低 12 位(位 0 到 11):將其設置為時間戳的位 48 到 59,保持位權重順序一致。
  6. 設置時間高位及版本欄位的高 4 位:將這 4 位(位 12 到 15)設置為對應於所創建 UUID 版本的 4 位版本號。
  7. 設置時鐘序列低位欄位(clock_seq_low field):將其設置為時鐘序列的最低有效 8 位(位 0 到 7),同樣保持位權重順序一致。
  8. 設置時鐘序列高位及保留欄位的低 6 位(clock_seq_hi_and_reserved field 的位 0 到 5):將其設置為時鐘序列的最高有效 6 位(位 8 到 13),保持相同位權重順序。
  9. 設置時鐘序列高位及保留欄位的高 2 位:將這 2 位(位 6 和 7)分別設置為 0 和 1,以滿足版本 1 UUID 的標準格式要求。
  10. 設置節點欄位(node field):將其設置為 48 位的 IEEE MAC 地址,地址中的每一位都保持原有的位權重順序

V3 和 V5

對應協議的 4.3. Algorithm for Creating a Name-Based UUID

版本3或5的UUID設計用於從特定 命名空間(name space) 內的且在該命名空間內唯一的 名字(names) 生成UUID。這裡的名字(names)和命名空間(name space)的概念應該廣泛理解,不僅限於文本名稱。例如,一些命名空間包括功能變數名稱系統(DNS)、統一資源定位符(URLs)、ISO對象標識符(OIDs)、X.500區別名(DNs)以及編程語言中的保留字等。在這些命名空間內分配名稱和確保其唯一性的具體機制或規則不在本規範的討論範圍內。

對於這類UUID的要求如下:

  1. 在同一命名空間內,使用相同名稱在不同時間生成的UUID必須完全相同。
  2. 在同一命名空間內,使用兩個不同名稱生成的UUID應當是不同的(概率極高)。
  3. 在兩個不同命名空間內,使用相同名稱生成的UUID也應當是不同的(概率極高)。
  4. 如果兩個由名稱生成的UUID相同,則它們幾乎肯定是由同一命名空間內的相同名稱生成的。

生成基於名稱和命名空間的UUID的具體演算法步驟如下:

  1. 為給定命名空間內所有由名稱生成的UUID分配一個作為“命名空間ID”的UUID;參見附錄C中預定義的一些值。
  2. 選擇MD5 [4] 或SHA-1 [8] 其中的一種哈希演算法;如果不考慮向後相容性,建議優先使用SHA-1。
  3. 將名稱轉換為其命名空間規定的標準化位元組序列形式,並將命名空間ID以網路位元組序排列。
  4. 計算命名空間ID與名稱連接後的哈希值。
  5. 將哈希值的前四個八位組(octets 0-3)賦給時間低位欄位(time_low field)的前四個八位組。
  6. 將哈希值的第五和第六個八位組賦給時間中間欄位(time_mid field)的前兩個八位組。
  7. 將哈希值的第七和第八個八位組賦給時間高位及版本欄位(time_hi_and_version field)的前兩個八位組。
  8. 將時間高位及版本欄位的四位最顯著位(bit 12 至 15)設置為第4.1.3節中指定的相應4位版本號。
  9. 將哈希值的第八個八位組賦給時鐘序列高位及保留欄位(clock_seq_hi_and_reserved field)。
  10. 將時鐘序列高位及保留欄位的兩位最顯著位(bit 6 和 7)分別設置為0和1。
  11. 將哈希值的第九個八位組賦給時鐘序列低位欄位(clock_seq_low field)。
  12. 將哈希值的第十至第十五個八位組賦給節點欄位(node field)的前六個八位組。
  13. 最後,將生成的UUID轉換成本地位元組序

獲取 UUID V4

這裡就只介紹V4版本,因為V4是基於 隨機或者偽隨機來實現的,只要保證 保留位版本號 的固定,其他的隨機生成就好。

正則 + Math.random

利用Math.random() 方法生成隨機數。

function uuidv4() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = (Math.random() * 16 | 0), v = c == 'x' ? r : (r & 0b0011 | 0b1000);
    return v.toString(16);
  });
}

先固定好格式,執行replace,整體代碼不難,唯一需要提一下的是 (r & 0b0011 | 0b1000) 操作,這裡的作用就是設置保留位的值10

r & 0b0011               // 高位,即2,3位 變為 00
r & 0b0011 | 0b1000      // 高位,即2,3位 變為 10

舉個例子, 用9為例,其二進位 0b1001 &

0b1001 & 0b0011   => 0b0011
0b0011 | 0b1000   => 0b1011

crypto.randomUUID

現代瀏覽器也內置 Crypto: randomUUID() method , nodejs 15.6.0 版本以上就內置了crypto.randomUUID([options])

crypto.randomUUID()
// 4d93f326-3f48-4a43-929d-b6489f4754b5

URL.createObjectURL

function uuid() { 
    const url = URL.createObjectURL(new Blob([])); 
    // const uuid = url.split("/").pop(); 
    const uid = url.substring(url.lastIndexOf('/')+ 1); 
    URL.revokeObjectURL(url); 
    return uid; 
}
 uuid()
// blob:http://localhost:3000/ff46f828-1570-4cc9-87af-3d600db71304

上面方式產生的都是 v4版本,如果v4版本滿足需求,就沒有必要去引入第三方庫了。

你是否真的需要UUID

在前端,有序後需要給數據添加一個id作為組件的key,這時候理大多數情況是不需要UUID, 也許下麵的函數就滿足了你的需求。

let id = 0;
function getId () {
    return id++;
}

後起之秀 NanoID

npm網站, NanoID是這麼自我介紹的:

Nano ID 是一個精巧高效的 JavaScript 庫,用於生成短小、唯一且適合放在 URL 中的標識符字元串。這個工具提供了幾個關鍵特性:

  1. 體積小巧:Nano ID 的最小化和壓縮版本非常緊湊,大小僅為 116 位元組。
  2. 安全性:該庫使用硬體隨機數生成器來確保生成的 ID 具有高安全性,可以在集群環境中安全使用。
  3. 短小 ID:相較於 UUID(通常包含 A-Z、a-z、0-9 以及 - 符號,共 36 個字元),Nano ID 使用了更大的字元集(包括 A-Za-z0-9_-),從而將 ID 的長度從 36 個符號減少到了 21 個,更便於在有限空間中使用。
  4. 可移植性:Nano ID 已被移植到超過 20 種編程語言中,具有良好的跨平臺適用性。

從最新的一周的下載量來對比,首先都是絕對的熱門庫,其次NanoID勢頭很盛。

截圖_20241305051331.png

借用 阿通 給的對比文案:

Nano ID 和 UUID(Universally Unique Identifier)都是用於生成唯一標識符的機制,但它們之間存在一些關鍵差異:

  1. 長度與格式

    • UUID:標準UUID由32個十六進位數字組成,分為5組,每組之間用短橫線-分隔,例如 xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx,總長度為36個字元(包括連字元)。
    • Nano ID:Nano ID 可配置長度,但預設生成的是較短的字元串,通常包含21個字元,並且可以自定義字元集(預設為 A-Za-z0-9_-)。
  2. 唯一性保證

    • UUID:基於時間戳、MAC地址(對於v1 UUID)、隨機數(對於v4 UUID)等多種因素生成,理論上全球範圍內幾乎不可能重覆。
    • Nano ID:雖然也致力於生成唯一的ID,但由於其較短的長度,在沒有額外存儲或演算法保證的情況下,唯一性風險相對較大。不過,通過增大字元集和適當增加ID長度,Nano ID也能實現很高的唯一性概率。
  3. 應用場景

    • UUID:廣泛應用於資料庫鍵、資源標識符、網路協議等需要全局唯一性的場景,尤其在網路間不同系統間的交互中常見。
    • Nano ID:更適合於對ID長度要求嚴格的場合,如URL友好、前端顯示或者存儲空間有限的情況。
  4. 性能與存儲成本

    • UUID:由於較長的字元串長度,存儲和傳輸時可能會占用更多空間。
    • Nano ID:因其短小,Nano ID在存儲和帶寬消耗上更有優勢。
  5. 安全性

    • UUID v4 是基於強隨機性生成的,因此安全性較高,不易被預測。
    • Nano ID 也可以使用安全的隨機源生成,同樣能夠達到較高的安全性,但在預設設置下,考慮到生成長度和字元集的選擇,如果不在生成邏輯上做特殊處理以增加熵,其安全性可能不及UUID。

綜上所述,選擇Nano ID還是UUID取決於具體的應用需求,如果重視存儲效率和簡潔性,同時能接受合理的唯一性保證策略,則Nano ID可能更為合適;而在需要絕對唯一性和不考慮存儲效率的場景下,UUID往往是更好的選擇。

寫在最後

不忘初衷,有所得,而不為所累,如果你覺得不錯,你的一贊一評就是我前行的最大動力。

微信公眾號:成長的程式世界 ,關註之後,海量電子書,打包拿走不送。

或者添加我的微信 dirge-cloud,一起學習。

引用

RFC4122: A Universally Unique IDentifier (UUID) URN Namespace
UUID那些事


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 作者本人使用的是vmware17Pro虛擬機,大家可以去網上找相關教程下載安裝,此總結後邊有多次安裝遇到的bug,要是有地方不妥,歡迎相互交流 在剛開始時,我們先部署的是Linux虛擬機,在設置Linux系統基礎環境時,系統就基本具有一些網路服務功能,差不多類似於現實中大型的伺服器,還有設置網路這一 ...
  • 近年來,新質生產力、數據要素及數據資產入表等新興概念猶如一股強勁的浪潮,持續衝擊並革新著企業數字化轉型的觀念視野,昭示著一個以數據為核心驅動力的新時代正穩步啟幕。 面對這些引領經濟轉型的新興概念,為了更好地服務於客戶並提供切實可行的實踐指導,自3月20日起,袋鼠雲將推出全新《袋鼠雲大數據實操指南》系 ...
  • 本文分享自華為雲社區《GaussDB(分散式)實例故障處理》,作者:subverter。 一、說明 GaussDB Kernel實例出現故障時,可以按照本節的辦法進行實例快速修複。 1、執行gs_om -t status --detail查看集群狀態,cluster_state為Normal,bal ...
  • 近日,以“行業更優數據底座,華為雲資料庫創新發展論壇”為主題的資料庫分論壇,通過對雲原生資料庫的發展與展望、技術實踐分享與研討,共同探索行業數字化轉型最優解。 ...
  • Android 逆向(四) - adb常用逆向命令 本篇文章繼續記錄下adb 的一些常用逆向命令. 1: adb shell ps 該命令可以查看進程信息. 用法: adb shell ps |grep [pname] zh@zh:~/workSpace$ adb shell ps USER PID ...
  • linux 入門(四) 1: 文件夾下所有文件的大小和詳細信息 du -h --max-depth=1 | sort -hr du命令可以查看文件夾(文件)占用的磁碟大小 ls命令可以查看文件的詳細信息,包括文件大小。 該命令可以按照文件夾(文件)大小的降序排列,並以易讀的方式顯示文件夾(文件)大小 ...
  • 一.引言 在當前的移動開發生態中,跨平臺框架如uni-app因其高效、靈活的特點受到了開發者們的青睞。同時,隨著物聯網技術的飛速發展,智能列印設備已成為許多業務場景中不可或缺的一環。今天,我們就來探討如何使用uni-app輕鬆對接馳騰品牌的智能印表機,實現無線列印功能。無論您是初學者還是有經驗的開發 ...
  • 我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 本文作者:霜序 本文首發於:https://juejin.cn/post/7299384698882539574 在大數據業務中,時常會出現且或關係邏輯的拼接,有需要做 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...