ابزار تولید ULID: شناسههای کوتاه، مرتبشدنی و ایمن برای وب
این صفحه ابزاری را ارائه میدهد که با انتخاب قالب ULID و تعیین تعداد (بین ۱ تا ۱۰۰)، فهرستی از شناسههای یکتا، ۲۶ کاراکتری و مرتبشدنی بر اساس زمان تولید میکند. برخلاف دیگر قالبهای همین ابزار (مانند UUID)، ULID دارای ۲۶ کاراکتر در مقابل ۳۶ کاراکتر UUID است و تنها از الفبای Crockford base32 استفاده میکند – یعنی حروف بزرگ و کوچک را یکسان در نظر میگیرد و هیچ خط تیرهای ندارد. ده کاراکتر اول ULID یک زمانمهر با دقت میلیثانیه را رمزگذاری میکند که امکان مرتبسازی واژهنامهای (lexicographic) بر اساس زمان ایجاد را فراهم میسازد. همچنین ULID بدون نیاز به escape کردن در URL امن است. در این صفحه هیچ گزینهای برای تغییر حروف بزرگ/کوچک یا افزودن خط تیره وجود ندارد، زیرا ULID ذاتاً case-insensitive و بدون خط تیره است.
ساختار درونی ULID: ۱۲۸ بیت در ۲۶ کاراکتر
ULID یک شناسه ۱۲۸ بیتی است که از دو بخش تشکیل شده است:
- ۴۸ بیت اول (۱۰ کاراکتر ابتدایی): زمانمهر با دقت میلیثانیه. این بخش با استفاده از الفبای Crockford base32 به ۱۰ کاراکتر تبدیل میشود. برای مثال، اگر زمان ایجاد
1469918176385میلیثانیه از Unix epoch باشد، کاراکترهای اولیهای مانند01ARZ3NDEKرا تولید میکند. - ۸۰ بیت بعدی (۱۶ کاراکتر پایانی): بخش تصادفی. این ۸۰ بیت توسط
crypto.getRandomValues()در مرورگر تولید میشود و هیچ سروری درگیر نیست. الفبای Crockford base32 شامل ارقام ۰-۹ و حروف A-Z (به جز I، L، O، U) است تا از اشتباهات بصری مانند تشابه 1 با I یا 0 با O جلوگیری شود.
نتیجه نهایی: یک رشته ۲۶ کاراکتری مانند 01ARZ3NDEKTSV4RRFFQ69G5FAV که حروف آن بزرگ یا کوچک باشند فرقی ندارد (مثلاً 01arz3ndektsv4rrffq69g5fav معادل است). کل فضای ۱۲۸ بیتی ULID برابر با فضای UUID است، اما نمایش آن ۱۰ کاراکتر کوتاهتر است.
جدول مقایسه ULID و UUID v4
| ویژگی | ULID | UUID v4 |
|---|---|---|
| طول رشته | ۲۶ کاراکتر | ۳۶ کاراکتر (شامل ۴ خط تیره) |
| فضای بیتی | ۱۲۸ بیت | ۱۲۸ بیت |
| الفبا | Crockford base32 (case-insensitive) | هگزادسیمال (case-insensitive) |
| حساسیت به حروف | خیر (حروف بزرگ/کوچک معادل) | خیر (اما گاهی به حروف کوچک رایج است) |
| خط تیره | ندارد | ۴ خط تیره |
| مرتبپذیری | بله (بر اساس زمانمهر ۴۸ بیتی) | خیر (کاملاً تصادفی) |
| نیاز به escape در URL | ندارد | ندارد |
| قابلیت حدسزنی | بخش تصادفی ۸۰ بیت | بخش تصادفی ۱۲۲ بیت (نسخه ۴) |
مرتبسازی بر اساس زمان: مزیت و محدودیت
یکی از اصلیترین دلایل استفاده از ULID، امکان مرتبسازی واژهنامهای شناسهها بر اساس زمان ایجاد است. اگر دو ULID در میلیثانیههای متفاوت ساخته شوند، آن که زمان کمتری دارد (قدیمیتر) از نظر حروف الفبا کوچکتر خواهد بود. این ویژگی برای پایگاههای دادهای که از B-tree به عنوان ساختار ایندکس استفاده میکنند بسیار ارزشمند است، زیرا درج شناسههای جدید تقریباً به صورت صعودی انجام میشود و باعث کاهش نیاز به بازآرایی ایندکس میگردد.
اما یک محدودیت مهم: ULID تضمین نمیکند که شناسههای تولید شده در یک میلیثانیه به ترتیب زمان ایجاد مرتب شوند. اگر چند ULID در همان میلیثانیه ساخته شوند، ترتیب آنها به بخش تصادفی بستگی دارد. بنابراین نمیتوان تنها با تکیه بر ULID، ترتیب دقیق رویدادها را در سطح میلیثانیه تعیین کرد. برای کاربردهایی که نیاز به ترتیب دقیق دارند (مثلاً ثبت وقایع)، بهتر است یک فیلد زمان جداگانه با دقت بالاتر (مثلاً نانوثانیه) در نظر گرفته شود.
احتمال برخورد (Collision) و امنیت تولید
بخش تصادفی ULID ۸۰ بیت است. برای ارزیابی احتمال برخورد، میتوان از تقریب birthday paradox استفاده کرد. اگر روزانه یک میلیارد ULID (۱۰^۹) تولید شود، احتمال یک برخورد در آن روز تقریباً ۱ در ۳.۷×۱۰^۱۳ است – یعنی عملاً صفر. با این حال، اگر تولیدکنندهای با نرخ بالا (مثلاً ۱۰ میلیون در ثانیه) کار کند، احتمال برخورد در طول ۲۴ ساعت به حدود ۱ در ۳۷۰۰ میرسد. بنابراین برای سیستمهای توزیعشده با نرخ تولید بسیار بالا، توصیه میشود که یک شناسه منحصربهفرد گره (node ID) به بخش تصادفی اضافه شود (مثلاً با گرفتن چند بیت از ۸۰ بیت تصادفی برای کد گره). ابزار حاضر این قابلیت را ندارد و تنها از randomness مرورگر استفاده میکند.
همه تولیدها به صورت محلی (سمت کاربر) با crypto.getRandomValues() انجام میشود و هیچ دادهای به سرور ارسال نمیگردد. این امر حریم خصوصی کاربران را حفظ میکند و بر خلاف سرویسهای آنلاین دیگر که شناسهها را روی سرور میسازند، امکان نشت اطلاعات وجود ندارد. همچنین از زمان سیستم مرورگر برای timestamp استفاده میشود، بنابراین اگر ساعت سیستم کاربر دقیق نباشد، مرتبسازی بین دستگاههای مختلف دچار اختلال میشود.
کاربردهای اصلی ULID
- توسعهدهندگان وب و موبایل: به جای UUIDهای ۳۶ کاراکتری که در URL یا ذخیرهسازی دست و پا گیر هستند، ULID کوتاهتر و قابل خواندنتر است. از آنجا که case-insensitive است، کاربران در تایپ دستی آن کمتر اشتباه میکنند.
- مدیران پایگاه داده: شناسههای زمانمرتب باعث بهبود عملکرد ایندکسهای B-tree میشوند. اگر از UUID v4 تصادفی استفاده کنید، هر درج جدید باعث میشود صفحهای تصادفی از ایندکس بهروز شود که fragmentation را افزایش میدهد. ULID این مشکل را کاهش میدهد.
- معماران سیستمهای توزیعشده: در سیستمهایی که چندین گره بدون هماهنگی مرکزی شناسه تولید میکنند، ULID با اختصاص یک prefix گره (اختیاری) قابل استفاده است. هرچند ابزار ما این قابلیت را ندارد، اما ساختار ULID اجازه میدهد که بخش تصادفی را به دو بخش تقسیم کرد: ۴۰ بیت تصادفی گره + ۴۰ بیت تصادفی شمارنده.
- طراحان API: برای شناسههای عمومی که نباید قابل حدس باشند (مثل شناسه کاربران) ULID به دلیل ۸۰ بیت تصادفی، حدسپذیری بسیار پایینی دارد. در عین حال از آنجا که از حروف مبهم (I, L, O, U) استفاده نمیکند، کپی و انتقال آنها در ارتباطات شفاهی آسانتر است.
نحوه استفاده از ابزار و موارد حاشیهای
در این صفحه، قالب از پیش روی ULID تنظیم شده است. دو ورودی اصلی دارید:
- Count (تعداد): یک عدد صحیح بین ۱ تا ۱۰۰. خارج از این بازه پذیرفته نمیشود.
- دکمه تولید: با کلیک روی آن (یا تغییر هر گزینه) فهرست جدیدی از ULIDها تولید میشود.
خروجی شامل:
- یک لیست عمودی از رشتههای ULID (تعداد برابر با count).
- نمایش تعداد تولید شده (مثلاً "تعداد: ۵").
- وضعیتهای "آماده"، "تولید شد" و "همه کپی شد" (زمانی که کل لیست را کپی کنید).
نکات مهم:
- با کلیک روی هر ULID به صورت مجزا، آن شناسه در کلیپبورد کپی میشود.
- تغییر هر یک از پارامترها (فرمت، تعداد،...) باعث تولید مجدد تمام شناسهها میشود.
- هیچ گزینهای برای حروف بزرگ یا کوچک وجود ندارد زیرا ULID به صورت پیشفرض case-insensitive است.
- خط تیره در ULID وجود ندارد و ابزار هیچ خطتیرهای اضافه نمیکند.
یک نکته فنی: Ulidهای تولید شده در این ابزار با استفاده از زمان فعلی مرورگر (Date.now()) و random واقعی ساخته میشوند. اگر بین دو تولید فاصله میلیثانیهای وجود داشته باشد، timestamp آنها متفاوت خواهد بود. اما زمانی که تعداد زیادی ULID در یک زمان (مثلاً ۱۰۰ عدد) درخواست میکنید، همه آنها timestamp یکسان (زمان کلیک) دریافت میکنند و تنها بخش تصادفی آنها فرق میکند.
پرسشهای متداول (FAQ)
۱. آیا ULID با UUID v4 سازگار است؟
خیر. این دو قالب متفاوت هستند. ULID ۲۶ کاراکتر و بدون خط تیره است، در حالی که UUID v4 ۳۶ کاراکتر با خط تیره دارد. اما هر دو ۱۲۸ بیت فضا دارند و میتوانند به عنوان کلید اصلی در پایگاه داده استفاده شوند.
۲. آیا ULID تاریخ ایجاد را مخفی میکند؟
بله و خیر. ۱۰ کاراکتر اول زمان ایجاد را به میلیثانیه نشان میدهند، بنابراین هر کسی که ULID را ببیند میتواند زمان تقریبی ایجاد آن را محاسبه کند. اگر به حریم زمانی نیاز دارید، نباید از ULID استفاده کنید یا باید timestamp را رمزگذاری کنید.
۳. تفاوت ULID و NanoID چیست؟
NanoID یک شناسه تصادفی با طول متغیر (معمولاً ۲۱ کاراکتر) است که از الفبای URL-safe استفاده میکند. NanoID مرتبپذیر نیست و timestamp ندارد. ULID دارای ۲۶ کاراکتر ثابت و مرتبپذیری زمانی است. NanoID از نظر طول کوتاهتر است اما ۱۲۸ بیتی نیست (معمولاً ۶۴ بیت تصادفی دارد).
۴. آیا امکان برخورد ULID در این ابزار وجود دارد؟
بله، اما احتمال آن بسیار کم است. با ۸۰ بیت تصادفی و تولید حداکثر ۱۰۰ ULID در هر بار، احتمال برخورد عملاً صفر محسوب میشود. اما اگر روزانه میلیونها ULID توسط کاربران مختلف تولید شود، احتمال برخورد جمعی افزایش مییابد. از آنجا که هر بار تولید از random جداگانه مرورگر استفاده میکند، برخورد بین جلسات مختلف نادر اما ممکن است.
۵. چرا ULID از خط تیره استفاده نمیکند؟
طراحان ULID عمداً خط تیره را حذف کردند تا طول رشته کوتاهتر شود و در URL بدون نیاز به escape قابل استفاده باشد. همچنین در برخی الفباها خط تیره ممکن است با عملگر منها اشتباه گرفته شود.
۶. آیا میتوانم تعداد ULID بیشتر از ۱۰۰ تولید کنم؟
خیر. این ابزار تنها تولید ۱ تا ۱۰۰ شناسه را در هر بار پشتیبانی میکند. برای تولید تعداد بیشتر باید چند بار درخواست دهید. این محدودیت برای جلوگیری از فشار بر مرورگر (به دلیل محاسبات random) در نظر گرفته شده است.