1. 先聊清楚:UUID到底是什么
你有没有思考过这样一个问题:当你在两个完全不相干的系统里各自生成一条数据,如何保证这两条数据的编号永远不会撞车?这是我在做分布式系统时被问过最多的问题之一,而每次我都会用同一个答案来回应:UUID,通用唯一识别码(Universally Unique Identifier)。
说白了,UUID就是给数据发“身份证”的机制。这串看似乱码的字符串,由 32 个十六进制字符组成,通常写成 8-4-4-4-12 的五段格式,比如 5a63e613-1f8d-4a2e-9c7b-0a2f1e3d9c8b,全算上连字符一共 36 个字符。它不需要中心服务器分配,任何一台设备、任何时候、只要按照标准算法独立生成,理论上全局唯一。
它能解决什么问题?最典型的就是“分布式场景下的数据合并”。假设你有十台数据库节点同时写入订单数据,如果每台节点都用自增 ID,两个订单很可能都叫 10086,合并时就冲突了。UUID 的思路是:你不是要一个“有顺序的短编号”,你只是要一个“不会重复的标识”,那我给你一个 128 位的大随机数就行。这个思路特别朴素,但真正做起来有很多细节值得聊。
这篇文章适合谁看?后端开发、数据库运维、桌面运维、甚至经常用 Excel 整理数据表的普通办公族。因为有几个人搜得特别勤的词——分布式UUID、Excel写UUID、Linux U盘UUID、Windows 11 获取主板UUID——这几个场景我都准备展开讲透。别急,一个都不落下。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. UUID的版本与选型:为什么分布式场景首选“随机版”
2.1 五段格式背后藏着版本信息
UUID 有五个版本,v1 到 v5,外加一个 v1 的变体。你不需要背全,但至少要能分辨两个最常用版本。关键看五段格式里的第三段的开头数字,比如 5a63e613-1f8d-4a2e-9c7b-0a2f1e3d9c8b,第三段 4a2e 首位是 4,这就是 v4 版本,也就是纯随机版。
各版本的差异我整理成了一张表:
| 版本 | 生成依据 | 唯一性来源 | 典型特征 |
|---|---|---|---|
| v1 | 当前时间戳 + 节点MAC地址 | 时间 + 主机唯一标识 | 前几位随时间递增,可反解生成时间 |
| v3 | MD5哈希(命名空间 + 名字) | 相同输入必得相同UUID | 用于从确定性字符串生成 UUID |
| v4 | 加密安全随机数 | 122位随机位 | 不依赖时间、不依赖硬件,最通用 |
| v5 | SHA-1哈希(命名空间 + 名字) | 同 v3,但哈希算法更强 | 确定性生成,适用于同一文本多次生成 |
| v7 | 时间戳排序 + 随机数 | 时间有序 + 随机 | 兼顾唯一性与大致排序,新一代推荐 |
v1 的最大问题在于它依赖 MAC 地址。虽然理论上时间戳加 MAC 保证唯一,但 MAC 地址属于设备硬件信息,在一些重视隐私的场景里,拿 MAC 做 UUID 会带来信息泄露风险,而且从 UUID 里可以反推生成时间和网卡厂商。所以我自己的项目几乎不用 v1,默认首选 v4。
v4 版本使用 122 位随机数(128 位中扣除版本位和变体位),由加密安全伪随机数生成器产出。说到“加密安全”,这不是营销话术:普通 Math.random() 这类伪随机数生成器对于 UUID 场景存在碰撞概率隐患,而加密级随机数在统计学上不可预测,碰撞概率低到可以忽略。
2.2 为什么自增ID在分布式场景里很尴尬
这里要解释清楚“为什么非要UUID”的底层动机。单体应用时代,数据库自增 ID 是非常完美的主键方案。它短、有序、天然适合 B+ 树索引的聚簇存储,查起来也快。但一旦拆成多库多表或微服务架构,自增 ID 就露馅了。
你想想:如果两个订单库各自从 1 开始增长,合并数据的时候得做整体重排,而重排一旦涉及上下游关联表的外键,那就是一场灾难。有人会说,可以用“雪花算法”或者“号段模式”来做分布式 ID,这些方案确实存在,而且很多场景下表现优于 UUID。但它们都有一个前提:需要引入协调组件(比如数据库发号器、ZooKeeper、或者时间戳+机器号的设计)。
UUID 真正的优势是去中心化。你不需要任何协调节点,不需要网络通信,在完全离线的设备上生成的 UUID,拿到另一台设备上,不会和那边已存在的 UUID 重复。这种“离线生成、全局唯一”的特性,就是分布式场景下选它的根本原因。
2.3 128位随机数到底有多大,为什么可以放心用
很多人对“随机不会重复”有疑虑,这很正常。我想用一个类比来让你安心:地球上的沙子数量大约在 7.5×10^18 量级,而 UUID v4 的随机空间是 2^122,约等于 5.3×10^36。也就是说,UUID 可用的随机组合数量,比地球上所有沙子总和还多出 10 的 17 次方倍。
再换一个角度:如果每秒生成 10 亿个 UUID v4,持续万亿年,碰撞概率才达到 50%。所以对绝大多数业务系统来说,“随机不重复”这四个字是完全成立的。我用 v4 这些年的体会是:凡是遇到 UUID 重复的案例,要么是用了劣质伪随机数,要么是把 v4 截断存成了短字段,没有一次是算法本身的锅。
3. 动手实战:从Python到Excel,把UUID“造”出来
3.1 后端生成:Python里的uuid库实测
Python 标准库自带的 uuid 模块是生成 UUID 最省事的途径,不需要 pip install 任何额外依赖。我平时写脚本、造测试数据、生成分布式系统的主键值,都直接用它。
python复制import uuid
# 生成 v4 版本
uid = uuid.uuid4()
print(uid)
# 输出示例: 5a63e613-1f8d-4a2e-9c7b-0a2f1e3d9c8b
# 去掉连字符的紧凑形式
compact_uid = uid.hex
print(compact_uid)
# 输出示例: 5a63e6131f8d4a2e9c7b0a2f1e3d9c8b
# 生成 v1 时间版本
uid_v1 = uuid.uuid1()
print(uid_v1)
有一点值得提醒:uuid.uuid1() 在 Python 3.7 以上版本默认会读取本机 MAC 地址来生成节点信息,涉及隐私,且同一机器上短时间内高频调用时可能因为系统时钟回拨产生重复。我一般在代码里明确拒绝 uuid1(),除非有强时间溯源需求,否则一律 uuid4()。
批量生成时还有一个实用技巧:用列表推导式一次性生成多个 UUID,避免重复调用函数时产生代码冗余。还有一个冷门但很值得掌握的 API:uuid.UUID(hex="...") 可以手动解析现有字符串并校验合法性,这在清洗数据时非常有用。
3.2 前端生成:原生方法已经很好用
现在的浏览器环境已经有原生 API:crypto.randomUUID()。这是标准的 v4 实现,不需要任何第三方库,返回的就是带连字符的 36 字符字符串。
javascript复制// 现代浏览器直接调用
const uid = crypto.randomUUID();
console.log(uid);
// 输出示例: 5a63e613-1f8d-4a2e-9c7b-0a2f1e3d9c8b
需要注意两点。第一,crypto.randomUUID() 只在安全上下文(HTTPS 或 localhost)下可用,如果你在 HTTP 协议的测试环境调用,它会是 undefined 或者直接抛异常。第二,如果目标环境较旧(比如某些国产双核浏览器),需要降级方案。我常用的降级方法是用 crypto.getRandomValues 填充一个 16 字节的无符号整数数组,然后手动设置版本位和变体位,这样既保证随机质量,兼容性也比 randomUUID 更好。
javascript复制function fallbackUUID() {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
bytes[6] = (bytes[6] & 0x0f) | 0x40; // 版本位 -> 4
bytes[8] = (bytes[8] & 0x3f) | 0x80; // 变体位 -> 10
const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}
顺便多说一句,前端生成 UUID 最主要的使用场景不是当数据库主键,而是给一次会话、一个临时组件、一个追踪任务打上临时标识。有人会用它做“防重复提交”的幂等键,注意这里需要把键值传给后端并校验,否则前端的随机性无法阻止恶意的重复请求。
3.3 办公场景:Excel里写一列UUID
“Excel 写 UUID” 是近期搜得很热的关键词。说实话我第一次刷到这个词时有点意外,后来跟一些做运营、做数据统计的朋友聊天才发现:很多人在手动维护数据表时需要给每条记录生成唯一编号,以前靠人工复制一串随机字符串,既容易重复又费眼睛。其实 Excel 完全可以公式生成。
在 Excel 里直接生成真正随机的 UUID 并不轻松,因为标准 RAND 函数会产生浮点数,重复率在批量生成时并不理想。一个比较靠谱的做法是使用 RANDBETWEEN 从十六进制字符池中抽取字符,拼接成 8-4-4-4-12 格式。下面这条公式是我在数据清洗时自己写出来的:
code复制=CONCATENATE(
DEC2HEX(RANDBETWEEN(0, 4294967295), 8), "-",
DEC2HEX(RANDBETWEEN(0, 65535), 4), "-",
"4", DEC2HEX(RANDBETWEEN(0, 4095), 3), "-",
DEC2HEX(RANDBETWEEN(16384, 32767), 4), "-",
DEC2HEX(RANDBETWEEN(0, 4294967295), 8),
DEC2HEX(RANDBETWEEN(0, 65535), 4)
)
看着长,拆开其实就三步:用 RANDBETWEEN(0, 4294967295) 随机出 8 个十六进制位(4294967295 等于 16 的 8 次方减 1,也就是 FFFFFFFF),然后按照标准格式把数字转十六进制后拼接。版本位我直接写死为 4,变体部分用 RANDBETWEEN(16384, 32767) 保证首位是 8、9、A、B 之一。
在 Excel 中填写时需要留意:在单元格输入公式后,先按住 Ctrl + Enter 批量填充一列,然后再把公式转为“粘贴为值”,这样 UUID 就不会因 Excel 自动重算而每秒变一次。我见过有人把公式整列留在表里,每次打开文件数据都全部刷新,等于编号白做了。
3.4 数据库方案:把UUID生成还给它该在的地方
Excel 只是轻量场景,真正以高吞吐量生成 UUID 的地方是数据库。PostgreSQL 首推 gen_random_uuid(),它是 PG 内置函数,输出 v4 版本 UUID,不需要额外安装扩展。MySQL 则提供 UUID() 函数,还有一个 UUID_SHORT(),但要注意 UUID_SHORT() 不是标准 UUID,它是基于服务器启动时间和实例 ID 生成的 64 位整数,在某些场景下会重复,不推荐当作通用主键。
sql复制-- PostgreSQL 推荐写法
CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
order_no TEXT,
created_at TIMESTAMP DEFAULT now()
);
-- MySQL 推荐写法
CREATE TABLE orders (
id CHAR(36) PRIMARY KEY DEFAULT (UUID()),
order_no VARCHAR(64),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
MySQL 这里有两个坑。第一,DEFAULT (UUID()) 的括号必须加,MySQL 8.0 以前不支持表达式默认值,所以老版本只能通过触发器或者应用层生成 UUID 再插入。第二,主键字段类型建议用 CHAR(36) 而不是 VARCHAR(36),因为 UUID 长度固定,用 CHAR 省掉长度校验开销,查询性能也稍好一些。
提示:如果你在建表时把 UUID 主键设置成随机字符串,那么在 InnoDB 引擎下,因为聚簇索引按主键物理排序,随机值会带来大量随机页插入,引发页分裂。数据量小的时候无所谓,上了千万行你就会感受到写入变慢。后续我会专门聊这个问题的解法。
4. Linux下用UUID管理U盘和分区:告别设备名漂移
4.1 为什么挂载存储设备要用UUID,而不是 /dev/sdb
Linux 下的存储设备节点名如 /dev/sdb、/dev/sdc 并不稳定。今天插入的 U 盘可能是 sdb,明天换了 USB 口就变成 sdd,重启后名称也可能变化。如果在 /etc/fstab 里写死 /dev/sdb1,一次顺序变动就可能导致开机挂载失败,系统甚至会进入紧急模式。
UUID 在此刻的价值就体现出来了:它是存储设备在格式化时写入的全局唯一标识,只要文件系统没有被重新格式化,UUID 就不会变。所以用 UUID 配置挂载,才是可靠的做法。
4.2 查看U盘和分区UUID的三种方式
第一种也是最直观的:lsblk -f。它会列出所有块设备,并在每个分区旁边显示 UUID、文件系统类型和挂载点。第二条常用命令是 blkid,它输出更详细,包括 PARTUUID、文件系统类型和卷标。第三条方式是通过 /dev/disk/by-uuid/ 目录直接做符号链接反向查找。
实际操作一遍,插入 U 盘后先运行 lsblk -f,你会看到类似下面的输出:
bash复制$ lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1 vfat FAT32 5A63-E613 300M 10% /boot/efi
├─sda2 ext4 1.0 a4f7c2e3-9b1d-4c88-9e1a-5c6d0f2b8a11 400G 20% /
└─sda3 swap 1.0 7e5c2a8f-3d14-49b2-aa6d-0c9e7f2a1b34 [SWAP]
sdb
└─sdb1 vfat FAT32 MYUSB 1234-ABCD 7.4G 0% /media/user/MYUSB
sdb1 就是 U 盘,它的 UUID 是 1234-ABCD。注意 FAT32/exFAT 这类微软文件系统使用的 UUID 是 8 位短格式,而 ext4、XFS 等 Linux 文件系统的 UUID 是 36 字符标准格式。这二者都可以直接用于挂载,但写进 fstab 时要区分清楚。
如果 lsblk 没输出 UUID,有可能是文件系统损坏或者尚未格式化,这时用 blkid 的结果会更准确。如果你的系统里同时插了多块硬盘,blkid 输出内容较长,建议加上 grep 过滤设备名。
bash复制$ sudo blkid /dev/sdb1
/dev/sdb1: UUID="1234-ABCD" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="9c7b6a5f-01"
4.3 用UUID配置自动挂载:fstab实战
接下来演示如何把上面查到的 UUID 写进 /etc/fstab,实现开机自动挂载。假设 U 盘的 UUID 是 1234-ABCD,你想把分区挂载到 /mnt/usb_data,操作步骤如下。
首先创建挂载点目录 sudo mkdir -p /mnt/usb_data,然后编辑 fstab 文件,在末尾追加一行:
bash复制UUID=1234-ABCD /mnt/usb_data vfat defaults,noatime,uid=1000,gid=1000,umask=022 0 0
这一行里参数比较讲究,我来逐个解释。vfat 是文件系统类型,如果是 exFAT 则写成 exfat;defaults 表示默认挂载选项;noatime 避免 U 盘频繁更新访问时间,能延长闪存寿命;uid=1000,gid=1000 把挂载后的文件属主设定为当前用户,否则普通用户写入会报“权限不够”;umask=022 是权限掩码,意思是去掉 group 和 other 的写权限,属于常规安全配置。
修改完 fstab 不要忘记运行 sudo mount -a 测试,并且观察有无报错信息。这一步非常重要:fstab 语法错误最坏情况会造成系统启动失败,所以我每一次编辑完都会先运行测试,再考虑重启。
提示:U盘、SD卡这类可移动设备不建议直接写进 fstab 长期挂载。因为设备拔掉后再次开机,fstab 会尝试挂载一个不存在的 UUID,导致系统等待 90 秒或进入维护模式。正确做法是使用 systemd 的 automount 机制,或者使用桌面环境的 udisks2 自动挂载,只有固定硬盘才适合写进 fstab。
4.4 为什么U盘格式化后UUID变了
很多用户会问:UUID 不是说不变吗?怎么我把 U 盘格式化了一趟,UUID 就变了。这里要澄清:UUID 在文件系统创建时生成,格式化意味着重新创建文件系统,原来的 UUID 会被一个新的随机值覆盖。所以“格式化会变、不格式化不变”才是准确的说法。
如果你确实需要在格式化后保持 UUID 不变(比如 fstab 里已经引用了它),可以在格式化时显式指定新 UUID。以 FAT32 为例,用 mkfs.vfat -i 1234ABCD /dev/sdb1。这个 -i 参数会把磁盘的 UUID 设置为 1234-ABCD 对应的十六进制位。ext4 则用 tune2fs /dev/sdb1 UUID=... 直接改,但注意要先把文件系统卸载。
5. Windows 11下获取主板UUID:比你想的简单,但坑也不少
5.1 主板UUID是什么?它和文件系统UUID不是一回事
前面几节的 UUID 都是软件层面的标识,而 Windows 11 用户搜的“主板 UUID”指的是固件层(SMBIOS)里的 System UUID,它是一个由硬件厂商写入主板固件中的 128 位标识符。操作系统启动时从 SMBIOS 表读取这个值,用于软件授权、设备资产管理、整机唯一性校验。
这个 UUID 与 Intel 的“主板序列号”不同,与网卡 MAC 地址也不同。它不是靠系统软件生成的,存在的意义在于给整台电脑一个与硬件绑定的恒定身份。很多企业做 IT 资产盘点时,会采集这个值作为机器的唯一主键。
5.2 四种方法实测:PowerShell/WMIC/注册表/BIOS
最方便的方法是 PowerShell,在 Windows 11 上按下 Win + X,选择“终端(管理员)”,然后执行:
powershell复制(Get-CimInstance Win32_ComputerSystemProduct).UUID
运行后屏幕直接输出一行 36 字符的 UUID。如果追求更详细的硬件信息,可以同时查看厂商、产品名和序列号:
powershell复制Get-CimInstance Win32_ComputerSystemProduct | Select-Object UUID, Vendor, Name, SerialNumber
第二种传统方式是 WMIC 命令。Windows 11 系统自带 WMIC,虽然在较新版本中微软默认禁用,但你依然可以在“命令提示符”里试试:
cmd复制wmic csproduct get uuid
如果提示“wmic 不是内部或外部命令”,说明系统已经默认移除,直接退回第一种方法。第三种方法需要查看主板本身的铭牌或包装盒,通常笔记本和品牌台式机都会把一系列条码贴在 D 面或内存仓盖板下。第四种方法就是开机进 BIOS 的 System Information 页面查,适合没有进系统的场景。
5.3 全F或全0:最常见的“无效UUID”是怎么回事
很多用户在 Windows 11 下执行上述命令后,输出的结果是 FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF 或者 00000000-0000-0000-0000-000000000000。这不是命令执行出错,而是主板固件里没有正确写入 System UUID。这种情况多见于 DIY 组装机或某些主板厂商为量产便利留空处理。
说实话,当你的主板 UUID 是这种“全 F 和全 0”值,软件授权商很可能拒绝承认这是一台有合法身份的电脑。如果你的电脑是品牌整机,请联系售后更新 BIOS 或咨询如何写入;如果是组装机,部分高端主板允许在 BIOS 的“UUID”菜单里手动输入字符串,但普通主板只能默认留空。从我的经验看,虚拟机里新建的 Windows 也会随机生成虚拟机的 UUID,所以如果你是在虚拟机测试,看到一串正常的随机值才符合预期。
5.4 主板UUID变了?排查思路记好三个方向
有同行反馈“重装系统后发现主板 UUID 变了”。很多情况下这只是信息收集上的误判,排查思路可以按下面三个方向来:
- 前后两次拿到的是否同一类 UUID。BIOS 里的 System UUID 和
Get-CimInstance取到的可能是不同来源,注意命令的区别。 - 是否刷过 BIOS。更新或重置 BIOS 固件,特别是从旧版本跨代更新,可能改写 SMBIOS 数据,导致 System UUID 变化。
- 是否存在双 BIOS/双主板切换。部分高端主板有 BIOS 备份切换功能,切换后 UUID 会切换为另一份固件里的值。
如果是硬件层面真的变了,比如更换主板或者官方维修,那属于“整机身份变更”,只能重新备案资产信息。企业资产管理上,常把主板 UUID 和硬盘序列号(HDD Serial)捆绑使用,两者同时变化才判定为硬件更替。
6. 高频踩坑实录:UUID使用中的七个常见问题
6.1 用 UUID 当数据库主键,会不会拖垮查询性能
随机 UUID 做主键最大的缺点是索引碎片化。InnoDB 的聚簇索引按照主键顺序排列,随机主键意味着新插入的行大概率落在已有数据块的中间而不是尾部,导致页分裂、写放大,进而拖慢写入性能。行数少没感觉,存量过千万之后你会发现 insert 越来越慢。
常规解法有两个:一是使用 UUID v7(时间有序版本),它既有 UUID 的唯一性,又能让索引大体按时间递增,兼顾性能和全局唯一;二是保留自增 BIGINT 主键,把 UUID 单独建立唯一索引,作为业务上的“逻辑ID”暴露给外部系统。我自己在订单中心项目里采用了后者,内部连接查询用自增主键,外部 API 对接用 UUID,两边都舒服。
6.2 Excel里生成的UUID粘到别处格式变了
Excel 默认把较长的字符串当作文本存储,但如果你的 UUID 是一串没有连字符的 32 位十六进制,Excel 在某些区域设置下可能把它识别为大数字或者科学计数法。最稳妥的办法是生成时保留连字符,并把单元格格式预先设置为“文本”。如果你已经有了一批没有连字符的数据,可以用文本函数给它补上,但没必要在 Excel 里硬拼,数据量可控的话直接用 Python 脚本统一处理更快。
6.3 Linux下用UUID挂载U盘后没有读写权限
这是新人最容易撞上的问题。U 盘的文件系统是 vfat(FAT32),Linux 挂载后如果不指定 uid/gid,默认 root 拥有文件,普通用户进目录看到文件却无法写入和删除。许多发行版在桌面环境下通过 udisks2 自动挂载时会自动设置好权限,但你手动 fstab 挂载就没有这个待遇。解决办法就是挂载参数里显式指定 uid/gid,也就是我上文 fstab 示例里的 uid=1000,gid=1000。如果不知道怎么查自己的 uid,运行 id -u 即可。
6.4 误以为“主板UUID=CPU序列号”的常识误区
有人会把主板 UUID 和 CPU 的序列号混为一谈。英特尔 CPU 的 ProcessorID 通常不会被操作系统直接读取,AMD 也没有公开稳定的 CPU 序列号接口,而主板 UUID 是固件层数据,和 CPU 没有任何关联。两者用途不同,也不能互相替代。如果你做软件授权,想知道绑定的是主板 UUID 还是磁盘序列号,授权方案里应该明确用哪几个硬件要素做指纹组合,单靠一个 UUID 做授权很容易被用户刷 BIOS 躲避。
6.5 同一个文件名反复生成UUID,结果竟然不一样
有需求场景是真要“同一个输入映射到同一个 UUID”,而不是每次随机。比如你在做数据迁移,需要为每行数据生成一个稳定标识,用 v4 随机版本就是每次运行结果不同,迁移第二次数据就全部对不上号。这时该用 v5 版本,它基于名字和命名空间做 SHA-1 哈希,同样的输入永远得到同样的 UUID。Python 里调用方式如下:
python复制import uuid
ns = uuid.NAMESPACE_DNS
same_id = uuid.uuid5(ns, "order-10086")
print(same_id)
# 每运行一次,结果都相同
这个用法在数据对账、ETL 管道、以及“主数据管理(MDM)”系统里非常常见。注意命名空间也要固定,同一个名字在不同命名空间下生成的 UUID 不同,混合使用会导致混乱。
6.6 小写还是大写,要不要保留连字符
UUID 标准写法允许大小写混用,但我在工程实践中建议:数据库里统一存小写、带连字符。理由很简单:主流语言的 UUID 库默认输出都是小写,POSTGRESQL 的 UUID 类型内部也按小写存储;如果应用层混用大小写,比如 Java 的 UUID.toString() 与 Python 的 str(uuid.uuid4()) 恰好都是小写,哪怕某天某个深坑因为大小写不同导致索引失效,排查成本很高。连字符务必保留,它不仅是分隔,也是 UUID 文本格式校验的一部分。你去掉连字符确实可以省几个字节,但换来的是无法用 UUID(hex=...) 直接解析,得不偿失。
6.7 UUID能不能截断使用
有一个“偷懒”做法在业务开发里非常常见:为了显示美观,把 UUID 截断成前 8 位或者后 6 位。我强烈建议不要这样做。截断后碰撞概率会指数级上升,可能几十万条数据就出现重复。如果真的需要短标识,应该用专门的短 ID 生成算法或者改造 UUID(比如把 128 位编码成 Base62),一定要保证信息量跟业务量匹配。
7. 把这些场景串起来:一套可复用的UUID知识框架
看到这里你应该已经意识到,UUID 不是一个孤立的“函数”,而是一整套在硬件、操作系统、数据库、办公软件里通用的事实标准。我最后一次梳理这些使用场景背后的共性与差异,让你以后拿到任何新环境都能快速举一反三。
无论是 Linux 的 blkid、Windows 的 PowerShell、Python 的 uuid 模块、Excel 的公式,还是数据库里的 gen_random_uuid(),它们都在做同一件事:利用一个足够大的标识空间,为对象分配一个独立且可传递的身份。差异只在于随机源的来源、受监管的设备信息、以及生成环境是否具备加密安全随机数。抓住这个内核,你就不会在某个具体平台上迷路。
我个人在实际项目中形成了一套较小的选型框架,分享给你参考:
- 只要“唯一标识、不需要排序”,一律选 v4 随机版;
- 如果数据量千万级以上且以插入为主,优先考虑 v7 有序版或单独的 BIGINT 主键+UUID 逻辑键;
- 如果要求稳定映射(同样输入同样输出),选 v5;
- 如果做文件系统挂载,直接把
lsblk -f查到的 UUID 填进 fstab; - 如果做整机身份绑定,用 Windows 的
(Get-CimInstance Win32_ComputerSystemProduct).UUID采集主板 UUID;遇到全0全F先查BIOS。
“唯一”从来不是一个绝对概念,而是在具体约束下的约定。UUID 的设计恰好把“唯一”的置信度抬高到了工程上可以完全信赖的程度。但说到底,如果你在真实的项目里发现两个“UUID”撞了,先别急着怪算法,多数时候是生成方式、存贮格式或者截断策略出了问题。沿着我上面整理的排查思路,几乎每次都能定位到问题根源。
