天天看點

講真!ULID 比 UUID 好用多了……

作者:dbaplus社群

ULID :Universally Unique Lexicographically Sortable Identifier(通用唯一詞典分類辨別符)

UUID :Universally Unique Identifier(通用唯一辨別符)

為什麼不選擇UUID

UUID 目前有 5 個版本:

版本1:在許多環境中是不切實際的,因為它需要通路唯一的,穩定的MAC位址,容易被攻擊;

版本2:将版本 1 的時間戳前四位換為 POSIX 的 UID 或 GID,問題同上;

版本3:基于 MD5 雜湊演算法生成,生成随機分布的ID需要唯一的種子,這可能導緻許多資料結構碎片化;

版本4:基于随機數或僞随機數生成,除了随機性外沒有提供其他資訊;

版本5:通過 SHA-1 雜湊演算法生成,生成随機分布的ID需要唯一的種子,這可能導緻許多資料結構碎片化;

這裡面常用的就是 UUID4 了,但是,即使是随機的,但是也是存在沖突的風險。

和 UUID 要麼基于随機數,要麼基于時間戳不同,ULID 是既基于時間戳又基于随機數,時間戳精确到毫秒,毫秒内有1.21e + 24個随機數,不存在沖突的風險,而且轉換成字元串比 UUID 更加友好。

ULID特性

ulid() # 01ARZ3NDEKTSV4RRFFQ69G5FAV           
  • 與UUID的128位相容性
  • 每毫秒1.21e + 24個唯一ULID
  • 按字典順序(也就是字母順序)排序!
  • 規範地編碼為26個字元串,而不是UUID的36個字元
  • 使用Crockford的base32獲得更好的效率和可讀性(每個字元5位)
  • 不區分大小寫
  • 沒有特殊字元(URL安全)
  • 單調排序順序(正确檢測并處理相同的毫秒)

ULID規範

以下是在python(ulid-py)中實作的ULID的目前規範。二進制格式已實作

01AN4Z07BY      79KA1307SR9X4MV3


|----------|    |----------------|
 Timestamp          Randomness
  10chars            16chars
   48bits             80bits           

組成

時間戳

  • 48位整數
  • UNIX時間(以毫秒為機關)
  • 直到公元10889年,空間都不會耗盡。

随機性

  • 80位随機數
  • 如果可能的話,采用加密技術保證随機性

排序

最左邊的字元必須排在最前面,最右邊的字元必須排在最後(詞彙順序)。必須使用預設的ASCII字元集。在同一毫秒内,不能保證排序順序

編碼方式

如圖所示,使用了Crockford的Base32。該字母表不包括字母I,L,O和U,以避免混淆和濫用。

0123456789ABCDEFGHJKMNPQRSTVWXYZ           

二進制布局和位元組順序

元件被編碼為16個八位位組。每個元件都以最高有效位元組在前(網絡位元組順序)進行編碼。

0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      32_bit_uint_time_high                    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     16_bit_uint_time_low      |       16_bit_uint_random      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       32_bit_uint_random                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       32_bit_uint_random                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+           

應用場景

  • 替換資料庫自增id,無需DB參與主鍵生成
  • 分布式環境下,替換UUID,全局唯一且毫秒精度有序
  • 比如要按日期對資料庫進行分區分表,可以使用ULID中嵌入的時間戳來選擇正确的分區分表
  • 如果毫秒精度是可以接受的(毫秒内無序),可以按照ULID排序,而不是單獨的created_at字段

用法(python)

安裝

pip install ulid-py           

建立一個全新的ULID。

時間戳記值(48位)來自 time.time(),精度為毫秒。

随機值(80位)來自 os.urandom()。

>>> import ulid
>>> ulid.new()
<ULID('01BJQE4QTHMFP0S5J153XCFSP9')>           

根據現有的128位值(例如UUID)建立新的ULID 。

支援ULID值類型有 int,bytes,str,和UUID。

>>> import ulid, uuid
>>> value = uuid.uuid4()
>>> value
UUID('0983d0a2-ff15-4d83-8f37-7dd945b5aa39')
>>> ulid.from_uuid(value)
<ULID('09GF8A5ZRN9P1RYDVXV52VBAHS')>           

從現有時間戳值(例如datetime對象)建立新的ULID 。

支援時間戳值類型有int,float,str,bytes,bytearray,memoryview,datetime,Timestamp,和ULID

>>> import datetime, ulid
>>> ulid.from_timestamp(datetime.datetime(1999, 1, 1))
<ULID('00TM9HX0008S220A3PWSFVNFEH')>           

根據現有的随機數建立一個新的ULID。

支援随機值類型有int,float,str,bytes,bytearray,memoryview,Randomness,和ULID。

>>> import os, ulid
>>> randomness = os.urandom(10)
>>> ulid.from_randomness(randomness)
>>> <ULID('01BJQHX2XEDK0VN0GMYWT9JN8S')>           

一旦有了ULID對象,就有多種與之互動的方法。

timestamp()方法将為您提供ULID的前48位的時間戳快照,而randomness()方法将為您提供後80位的随機數快照。

>>> import ulid
>>> u = ulid.new()
>>> u
<ULID('01BJQM7SC7D5VVTG3J68ABFQ3N')>
>>> u.timestamp()
<Timestamp('01BJQM7SC7')>
>>> u.randomness()
<Randomness('D5VVTG3J68ABFQ3N')>           

github:https://github.com/ahawker/ulid

作者丨pushiqiang

來源丨網址:blog.csdn.net/pushiqiang/article/details/117365290

dbaplus社群歡迎廣大技術人員投稿,投稿郵箱:[email protected]

活動推薦

2024 XCOPS智能運維管理人年會·廣州站将于5月24日舉辦,深究大模型、AI Agent等新興技術如何落地于運維領域,賦能企業智能運維水準提升,建構全面運維自治能力!

講真!ULID 比 UUID 好用多了……

會議詳情:2024 XCOPS智能運維管理人年會-廣州站