CUID چیست؟
CUID (شناسه یکتای مقاوم در برابر تصادم) یک الگوریتم متنباز برای تولید شناسههای یکتا است که بدون نیاز به هماهنگکننده مرکزی در سیستمهای توزیعشده بهخوبی کار میکند. بر خلاف UUID ساده، CUID برای مقیاسپذیری افقی طراحی شده است — چندین سرور یا تب مرورگر میتوانند مستقلاً شناسه تولید کنند با کمترین احتمال تصادم.
هر CUID با حرف کوچک c شروع میشود و فرمت آن را در نگاه اول قابل تشخیص میکند. کاراکترهای باقیمانده همه حروف و اعداد کوچک (base36) هستند، پس CUID ایمن برای URL است و میتوان آن را مستقیماً به عنوان بخشی از مسیر URL یا کلید اصلی پایگاه داده بدون رمزگذاری اضافی استفاده کرد.
مشخصات اصلی CUID (نسخه ۱) توسط اریک الیوت ایجاد شد و از طریق بسته cuid در npm رواج یافت. اکنون توسط CUID نسخه ۲ جایگزین شده که امنیت رمزنگاری ارائه میدهد. این صفحه — و ابزار بالا — شناسههای CUID نسخه ۱ تولید میکند، فرمت کلاسیکی که هنوز بهطور گسترده در کدبیسهای تولیدی دیده میشود.
ساختار CUID
یک CUID نسخه ۱ تقریباً ۲۵ کاراکتر دارد و از پنج بخش متصلشده تشکیل میشود که هر کدام نوع متفاوتی از آنتروپی را حمل میکنند:
بخشها بهسادگی به هم متصل میشوند — هیچ جداکنندهای وجود ندارد. طول کل بسته به مقدار زماننگار جاری کمی تغییر میکند اما تقریباً ۲۵ کاراکتر باقی میماند.
چگونه CUID از تصادم جلوگیری میکند
مقاومت در برابر تصادم از لایهبندی منابع مستقل آنتروپی ناشی میشود. حتی در بدترین سناریوها — هزاران شناسه تولیدشده در هر میلیثانیه روی چندین دستگاه — احتمال تولید دو شناسه یکسان بسیار ناچیز است.
CUID در مقابل UUID نسخه ۴
هر دو CUID و UUID نسخه ۴ برای تولید شناسه در سمت کلاینت بهطور گسترده استفاده میشوند. آنها با رویکردهای متفاوتی با همان مشکل روبرو میشوند:
| ویژگی | CUID نسخه ۱ | UUID نسخه ۴ |
|---|---|---|
| فرمت | c + base36 (~۲۵ کاراکتر) | گروههای هگزادسیمال (۳۶ کاراکتر با خط تیره) |
| قابل مرتبسازی | تقریباً (پیشوند زماننگار) | خیر |
| ایمن برای URL | بله (فقط حروف و اعداد) | عمدتاً (خط تیره در URLها قابل قبول است) |
| مقاومت در برابر تصادم | بالا — زماننگار + شمارنده + اثر انگشت + تصادفی | بالا — ۱۲۲ بیت تصادفی |
| قابلیت پیشبینی | جزئی (زماننگار قابل مشاهده) | هیچ (کاملاً تصادفی) |
| طول | ~۲۵ کاراکتر | ۳۶ کاراکتر |
| نیاز به هماهنگی | خیر | خیر |
UUID نسخه ۴ برای سناریوهای حساس به امنیت گزینه ایمنتری است زیرا هیچ اطلاعاتی از زمانبندی فاش نمیکند. CUID زمانی برتری دارد که شناسههای کوتاهتر، بدون خط تیره و کمابیش قابل مرتبسازی بخواهید. این ویژگیها آن را برای URLها، نام فایلها یا لاگها مناسب میکند — جایی که میخواهید از روی شناسه، زمان ایجاد رکورد را تشخیص دهید.
CUID نسخه ۱ در مقابل CUID نسخه ۲
مشخصات CUID بهطور قابل توجهی تجدیدنظر شده است. درک تفاوتها به شما کمک میکند نسخه مناسب را برای پروژهتان انتخاب کنید:
| جنبه | CUID نسخه ۱ | CUID نسخه ۲ |
|---|---|---|
| الگوریتم | اجزای قطعی | مبتنی بر SHA-3، کاملاً مبهم |
| رمزنگاری | خیر | بله |
| زماننگار قابل مشاهده | بله | خیر |
| فرمت | با «c» شروع میشود | با «c» شروع میشود (قابل تنظیم) |
| بسته npm | @paralleldrive/cuid (منسوخ) | @paralleldrive/cuid2 |
| طول | ~۲۵ کاراکتر | ۲۴ کاراکتر (پیشفرض، قابل تنظیم) |
برای پروژههای جدید، CUID نسخه ۲ گزینه توصیهشده است. ساختار مبتنی بر SHA-3 آن به این معناست که خروجی مبهم است — هیچ زماننگار، شمارنده یا اثر انگشتی از شناسه قابل مهندسی معکوس نیست. فقط زمانی از CUID نسخه ۱ استفاده کنید که به سازگاری با مجموعه داده موجود نیاز دارید یا یک پیادهسازی بدون وابستگی میخواهید.
موارد استفاده
@id برای کلیدهای اصلی رشتهای استفاده میکند — @default(cuid()) — که آن را به یکی از گستردهترین فرمتهای شناسه در اکوسیستم جاوااسکریپت تبدیل میکند.مثالهای کد
بسته CUID نسخه ۲ رسمی (توصیهشده) را نصب کنید یا یک پیادهسازی حداقلی نسخه ۱ بدون وابستگی بنویسید:
// 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'اگر یک پیادهسازی Node.js بدون وابستگی برای الگوریتم نسخه ۱ ترجیح میدهید:
// 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:
-- 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())
}