ID生成工具整理

UUID、ULID、SnowflakeId、Ksuid、NanoId等编号生成工具功能比较

前言

在设计软件时,数据主键的设计是一个很重要的事情,一条数据的编号关系到数据的唯一性判断与检索定位。

关系数据库理论里面提到了键(key,码)与主键(primary
key,主码),在例子里面一般都使用学号、产品编号等来演示。但并未过多提到这种唯一编号的生成方式。实践中,通常会用随机字符串、自增序列等方式作为唯一编号。

编号不仅会用于软件中的数据存储,也会用在数据交换、人机信息传递等场合。

本文整理几种常见编号生成算法(表格 1),并按照时间顺序介绍这些工具。

汇总表

表格 1 编号生成工具简表

名称(字母顺序) 长度(bits) 保留位(bits) 字符串长度(表示法) 优化时间排序 例子
Ksuid 160 0 27(base62) 2dJf4bxMcdyAo5UhH3EFJKOt380
MongoDB ObjectId 96 0 26(hex) ObjectId("507f1f77bcf86cd799439011")
Nano ID 128 2 21(base64) 随机 ofouG6h5HRadNRgW_atUB
SnowflakeId 64 1 19(10进制) 9223372036854775807
ULID 128 0 26(base32) 01HR9YEEJ9JP6TT2SSF72QDTF6
UUIDv1 128 6 36(hex) 随机 23ab203a-b193-1016-b803-9600026de545
UUIDv4 128 6 36(hex) 随机 07e964b7-3fb5-46fe-b07f-61ec69dbe9ae
UUIDv6 128 6 36(hex) 016b1932-3daa-6b61-b804-45014d54d2ff
UUIDv7 128 6 36(hex) 018e13e7-0e77-7ba6-a0e8-52b6bdb47eb7
UUIDv8 128 6 36(hex) 自定义 ——

UUID

Universally Unique Identifier(UUID),全局唯一标识,由RFC4122规范所定义。Windows系统中习惯叫做Globally Unique Identifier (GUID)。该规范在ISO/IEC及ITU-T同样有采用。

UUID可追溯到1980年代,当时Apollo 公司在设计网络计算系统(Network Computing System,NCS)时为了唯一地识别系统中的每个节点,于是提出UUID方案。后来,开放软件基金会(Open Software Foundation,OSF)设计的分布式计算环境(Distributed Computing Environment,DCE)以及微软的Windows平台中均有采用该方案。到1998年时,互联网工作组(Internet Engineering Task Force ,IETF)吸纳其成为标准,编号RFC4122。

UUID实质为一个128bits(16bytes)的二进制数,在其中保留6位用于协议识别。转换成10进制会有39位之长。

为了方便识别和阅读,同时设计一种标准的字符串表示法(16进制):xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx(8-4-4-4-12分隔,每个x实际为0-F的16进制字符)。Windows中还有用大括号括起来的形式{......}。有人也习惯把分隔符去掉来减少长度,但只有第一种是标准形式。UUID最小是(也叫Nil UUID):00000000-0000-0000-0000-000000000000,最大是:FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF

2003年时,注册申请到urn标识,可以写作:urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6

UUID发展出多个版本来适应不同需求,版本1-5发布于2005年之前。主要差异在于生成思路上,详细说明可以参考规范原文。

UUID v1 与 UUIDv4

UUID第三组前4个位是版本代号,第四组前2位是变体代号。

V1版( Gregorian Time-based UUID)使用机器的公历日期、时钟、随机数与MAC地址组合而成。例如“b375c417-b1ac-1016-b9af-9600026de545”。

V4版(Random)则全部使用随机数来组合,例如“9960b102-0639-4eef-8c2f-99074a6ccaab”。“java.util.UUID#randomUUID”采用的也是这一版设计。

UUIDv3 与 UUIDv5

V3(MD5 Name-based)与V5(SHA-1 Name-based)用于将指定名字空间(如DNS、URL、OID、X500)的名字转换成UUID表示法。不同的是v3采用MD5摘要算法,v5采用SHA-1。

举例:UUIDv3(URL,http://www.baidu.com)=2f67490d-55a4-395e-b540-457195f7aa95

V2(DCE Security)专用于DCE Security ,并未在RFC中讨论。

MongoDB ObjectId

2009年MongoDB数据库发布,里面设计有名为ObjectId的数据类型,也是一个主键生成算法。

ObjectId长度为96bits,由32位的Unix Epoch 时间戳、40位随机数(进程标识),24位顺序递增码(随机开始)组成。

可以表示成24位长的16进制数,例如“ObjectId("507f1f77bcf86cd799439011")

SnowflakeId

习惯叫雪花算法。2010 年Twitter 开源了他们团队在用的这种全局唯一ID生成工具。其特点是可用于分布式系统中各节点生成ID,可按照生成时间排序,不连续递增。

SnowflakeId是一个64 bits二进制数。为了避免负数,最高位永远置0,实际使用63 bits。由系统时间戳、机器识别码、顺序号组成。

在SnowflakeId基础上,发展出多种变体,如百度的、美团的、微信的等。

Ksuid

K-Sortable Unique Identifier(Ksuid)。Twilio Inc在比较了UUID、Snowflake ID的特点后,在2017年提出一种新的ID生成算法。特点是可按照生成时间排序,无协调机制,碰撞概率低。

设计为160 bits长,由32位时间戳、128位随机数组合而成,比UUID更长。使用Base62编码方式表示为27位长的字符串。例如“2dtpkbpDpweYidSNJZabF9xo5Cz”。

NanoId

NanoId ID,2017年,作者是Evil Martians。使用随机数来生成ID,并将数字值编码为字符串(base64),在128bit随机数的情况下,可以编码为21个字符。

字符串长度、字典表均可自行调整,方便在简便情况下生成更短的ID。与其相似的还有squids(曾经叫hashids)

ULID

Universally Unique Lexicographically Sortable Identifier。为了克服UUID(v1-v5)排序不便的问题,民间组织在2017年新提出的一种ID生成算法。

长度128 bits,由前48位时间戳、后80位随机数组成。可按时间排序,利于数据库索引。使用base32编码为长度为26的字符串。例如“01ARZ3NDEKTSV4RRFFQ69G5FAV”。

UUIDv6-v8

因被吐槽不能按时间排序,不利于数据库索引优化,而新设计的版本。从2021年开始设计,增加3个版本,目前提案已经定稿,等待审定公布。

V6(Reordered Gregorian Time-based) 与 v1生成思路接近,但字节序做了调整以支持时间排序,MAC地址则换成了随机数。

V7(Unix Time-based)进一步采用了Unix Epoch timestamp做时间戳,更接近主流的选择。

V8(Custom)则是一个完全自由的版本。除了固定的6位版本识别外,不定义生成方法,用户可以自己设计决定。这意味着你有122 bits可用,你可以将许多短于这个长度的ID编码成UUID。

未来应该会主推UUIDv7了。

小结

编号本质上是有状态服务,因为其要具备唯一性识别的作用。例如钞票的编号,发票的号码,身份证号码,订单号等。

编号生成一般依赖机器时钟、机器识别码、随机数或者中心化的编号池分配等设计。

在不同需求下编号生成的算法有所不同,自增序列、UUID是常见的方案。

参考资料

[1] https://datatracker.ietf.org/doc/draft-ietf-uuidrev-rfc4122bis/14/ —— rfc4122新草案
[2] https://segment.com/blog/a-brief-history-of-the-uuid/ —— UUID历史
[3] https://idtools.co/uuid/v1 —— 在线生成UUID的工具,可用于演示

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,682评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,277评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,083评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,763评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,785评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,624评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,358评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,261评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,722评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,900评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,030评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,737评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,360评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,941评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,057评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,237评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,976评论 2 355

推荐阅读更多精彩内容

  • 我们在实际编程过程中会经常遇到需要用唯一ID的场合,这些唯一ID还会存到数据库中以便于我们将来进行查询。 例如用户...
    小敢敢不憨a阅读 6,197评论 0 0
  • 序 本文主要来聊聊分布式id的生成方案。 目标 业务系统需要什么样的ID生成器中提出了几点目标: 唯一性 时间相关...
    go4it阅读 629评论 0 3
  • 格式 UUID(universally unique identifier) 长度是128 bit,也就是由32个...
    QiShare阅读 2,405评论 0 1
  • 一、交易订单号生成(雪花算法) 基本思路,int64 二进制64位。按位来划分业务字段。 从高位到地位: 几位含义...
    范柏柏阅读 3,934评论 0 0
  • 分布式 ID 介绍 什么是 ID? 日常开发中,我们需要对系统中的各种数据使用 ID 唯一表示,比如用户 ID 对...
    欢喜的看着书阅读 147评论 0 1