CUID v1生成器

Generate collision-resistant unique IDs (CUID v1)

数量

已生成的 CUID

点击"生成"以创建 CUID

CUID v1 是传统格式。新项目请使用 CUID2。

什么是 CUID?

CUID(碰撞抵抗唯一标识符)是一种开源算法,用于生成在分布式系统中无需中央协调器即可正常工作的唯一 ID。与简单的 UUID 不同,CUID 被设计为横向可扩展——多个服务器或浏览器标签可以各自独立生成 ID,碰撞风险极低。

每个 CUID 以小写字母 c 开头,使格式一眼即可识别。其余字符均为小写字母数字(base36),因此 CUID 对 URL 安全,可直接用作 URL 路径段或数据库主键,无需额外编码。

原始 CUID 规范(v1)由 Eric Elliott 创建,并通过 npm 包 cuid 推广。现已被提供密码安全性的 CUID v2 取代。本页面——以及上方的生成器——生成 CUID v1 ID,这是仍在生产代码库中广泛使用的经典格式。

CUID 结构

CUID v1 约 25 个字符长,由五个串联段组成,每段承载不同类型的熵:

示例: clrc4gkwz001ag2hs3k7f9m2q
c前缀始终是字母 "c"——标识 CUID
lrc4gkwz时间戳以 base36 表示的毫秒时间戳(约 8 个字符)
001a计数器4 位 base36 计数器——防止同毫秒内碰撞
g2hs指纹4 位 base36 主机指纹(浏览器/环境信息)
3k7f9m2q随机8 位 base36 随机块——两个 32 位值

这些段仅简单串联——没有分隔符。总长度根据当前时间戳值略有变化,但保持在约 25 个字符。

CUID 如何防止碰撞

碰撞抵抗来自于叠加独立的熵源,即使在最坏情况下(每毫秒跨多台机器生成数千个 ID)两个相同 ID 的概率也极低。

毫秒时间戳
第一段以 base36 编码当前时间。在不同时刻生成的 ID 自动按创建时间字典序排列——便于分页和调试。
单调计数器
在同一进程中,4 位计数器随每个生成的 ID 递增。即使两次调用发生在同一毫秒的同一台机器上,计数器也能保证每毫秒最多 65,536 个 ID 的唯一性。
机器指纹
从环境特定数据派生的哈希(Node.js 中的进程 ID + 主机名;浏览器中的屏幕尺寸 + navigator 信息)。这区分了在完全相同的毫秒内具有相同计数器值的不同主机上生成的 ID。
随机块
最后 8 个字符来自两个独立的 32 位随机值(以 base36 编码)。这添加了最后一层熵,即使两台机器的指纹恰好哈希到相同值,也能防止碰撞。

CUID vs UUID v4

CUID 和 UUID v4 都广泛用于客户端 ID 生成。它们对同一问题采取不同的方法:

特性CUID v1UUID v4
格式c + base36(约 25 字符)十六进制组(36 字符含连字符)
可排序大致可排序(时间戳前缀)
URL 安全是(仅字母数字)基本上(连字符在 URL 中可用)
碰撞抵抗高——时间戳 + 计数器 + 指纹 + 随机高——122 位随机
可预测性部分(时间戳可见)无(纯随机)
长度约 25 个字符36 个字符
需要协调

UUID v4 是安全敏感场景的更安全选择,因为它不泄露时间信息。当你需要大致可排序、更短且无连字符的 ID 时,CUID 更有优势——便于在 URL、文件名或日志中快速识别记录的创建时间。

CUID v1 vs CUID2

CUID 规范已进行了重大修订。了解差异有助于为你的项目选择正确版本:

方面CUID v1CUID v2
算法确定性组件基于 SHA-3,完全不透明
加密
时间戳可见
格式以 "c" 开头以 "c" 开头(可配置)
npm 包@paralleldrive/cuid(已弃用)@paralleldrive/cuid2
长度约 25 字符24 字符(默认,可配置)

对于新项目,推荐使用 CUID v2。其基于 SHA-3 的构造意味着输出是不透明的——无法从 ID 中逆向工程时间戳、计数器或指纹。仅在需要与现有数据集向后兼容或需要无依赖实现时才使用 CUID v1。

使用场景

分布式数据库
多个数据库分片或微服务可以各自独立生成主键,无需序列表或中央 ID 服务,消除单点故障。
客户端 ID 生成
浏览器可以在将新记录发送到服务器之前为其分配 CUID,实现乐观 UI 更新,并消除获取服务器分配 ID 所需的往返请求。
离线优先应用
在无连接情况下运行的移动或 PWA 应用可以创建具有稳定 ID 的记录,这些记录在同步后仍能存活——设备重新上线时不会发生冲突。
URL 短标识
CUID 仅包含字母数字字符,可安全地直接嵌入 URL 路径而无需百分比编码。时间戳前缀添加了大致的创建时间排序。
事件 / 日志关联
由于时间戳编码在第一段中,即使跨分布式日志聚合器,带有 CUID 标记的日志条目也可以按创建时间大致排序。
ORM / Prisma 默认值
Prisma 使用 CUID 作为字符串主键的默认 @id 策略——@default(cuid())——使其成为 JavaScript 生态系统中部署最广泛的 ID 格式之一。

代码示例

安装官方 CUID v2 包(推荐)或编写无依赖的最小 v1 实现:

JavaScript / TypeScript
// npm install @paralleldrive/cuid2  (recommended — CUID v2)
import { createId } from '@paralleldrive/cuid2'

const id = createId()
// → 'tz4a98xxat96iws9zmbrgj3a'

// Custom length
import { init } from '@paralleldrive/cuid2'
const createShortId = init({ length: 10 })
createShortId() // → 'zxp1l6mf4c'

如果你更喜欢 v1 算法的无依赖 Node.js 实现:

Node.js (no dependencies)
// Pure Node.js — CUID v1 style (no dependencies)
let counter = 0

function pad(str, size) {
  return str.padStart(size, '0').slice(-size)
}

function fingerprint() {
  const os = require('os')
  const source = [process.pid, os.hostname().length].join('')
  let hash = 0
  for (const c of source) {
    hash = ((hash << 5) - hash) + c.charCodeAt(0)
    hash |= 0
  }
  return pad(Math.abs(hash).toString(36), 4)
}

function cuid() {
  const timestamp = Date.now().toString(36)
  const cnt       = pad((counter++ & 0xffff).toString(36), 4)
  const fp        = fingerprint()
  const rnd       = pad(Math.floor(Math.random() * 0xffffffff).toString(36), 4)
              + pad(Math.floor(Math.random() * 0xffffffff).toString(36), 4)
  return 'c' + timestamp + cnt + fp + rnd
}

console.log(cuid()) // → 'clrc4gkwz001ag2hs3k7f9m2q'

使用 CUID 作为 Prisma 和 PostgreSQL 的数据库主键:

Prisma / SQL
-- Use CUID as a primary key in PostgreSQL
CREATE TABLE users (
  id   TEXT        PRIMARY KEY DEFAULT gen_cuid(),
  name TEXT        NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now()
);

-- Prisma schema (auto-generates CUID by default)
model User {
  id        String   @id @default(cuid())
  name      String
  createdAt DateTime @default(now())
}

常见问题

CUID 对 URL 安全吗?
是。CUID v1 仅使用小写字母和数字(base36 编码),这些都是 URL 安全字符。在 URL 路径或查询参数中使用 CUID 时不需要百分比编码。
CUID 具有密码安全性吗?
否。CUID v1 使用 Math.random() 并暴露可见的时间戳前缀。它不适合用于会话令牌或密码重置链接等安全敏感目的。对于这些用例,请使用 crypto.randomUUID() 或 CUID v2。
CUID vs NanoID——应该选择哪个?
NanoID 具有密码安全性,更短(默认 21 字符),并使用可自定义的字母表。当安全性重要或需要更短 ID 时选择 NanoID。当你想要大致可排序、带时间戳前缀且便于调试的 ID 时选择 CUID。
应该使用 CUID v1 还是 CUID v2?
CUID v2 是当前推荐。它具有密码安全性,不泄露时间信息,并且积极维护。当你需要简单的无依赖实现或维护遗留系统时,CUID v1 很有用。此生成器生成 CUID v1 ID。
CUID vs ULID——有什么区别?
两者都有时间戳前缀且按字典序可排序。ULID 使用 Crockford base32(总共 128 位,48 位时间戳 + 80 位随机),使其略微更随机。CUID 添加了机器指纹和单调计数器,这提高了同一主机在同一毫秒内的碰撞抵抗。ULID 排序更可靠,因为时间戳占据完整的高位部分。
CUID 能保证唯一吗?
没有中央协调器,任何 ID 方案都无法给出数学保证。CUID 通过组合四个独立的熵源(时间戳、每进程计数器、机器指纹和随机数据)使碰撞极不可能发生。实际上,碰撞比硬件故障的可能性小得多。