UUID v1 কী?
UUID v1 হলো UUID-এর মূল সংস্করণ, যা RFC 4122 (2005)-এ মানকীকৃত হয়েছে। এটি উচ্চ-নির্ভুলতার টাইমস্ট্যাম্পের সাথে তৈরিকারী হোস্টের MAC অ্যাড্রেস এবং সাব-টাইমস্ট্যাম্প রেজোলিউশন পরিচালনার জন্য একটি সংক্ষিপ্ত ক্লক সিকোয়েন্স মিলিয়ে অনন্য শনাক্তকারী তৈরি করে।
টাইমস্ট্যাম্প এমবেড থাকায়, একই হোস্ট থেকে UUID v1-এর মানগুলো সময়ের সাথে ক্রমশ বৃদ্ধি পায় — ফলে এগুলো স্বাভাবিকভাবেই ক্রমানুসারী। এটি বিতরণকৃত সিস্টেমের জন্য ডিজাইন করা হয়েছিল যেখানে প্রতিটি নোড কোনো সমন্বয় ছাড়াই স্বাধীনভাবে UUID তৈরি করতে পারে।
আজ UUID v1 মূলত UUID v7 (sortable, MAC ফাঁস নেই) এবং UUID v4 (সম্পূর্ণ র্যান্ডম, প্রাইভেট) দ্বারা প্রতিস্থাপিত হয়েছে। এটি Apache Cassandra এবং লেগ্যাসি বিতরণকৃত ডেটাবেসের মতো সিস্টেমে ব্যবহৃত হচ্ছে।
RFC 9562 — Universally Unique IDentifiers (UUID) →
UUID v1-এর গঠন
550e8400-e29b-11d4-a716-446655440000-এর মতো একটি UUID v1 স্ট্রিং ছয়টি স্বতন্ত্র ক্ষেত্র এনকোড করে:
| ক্ষেত্র | আকার | বিবরণ |
|---|---|---|
| time_low | 32 bits | ৬০-বিট গ্রেগরিয়ান টাইমস্ট্যাম্পের ৩২-বিট নিম্ন ক্ষেত্র (১৫৮২ সালের ১৫ অক্টোবর থেকে ১০০-ন্যানোসেকেন্ড ব্যবধান) |
| time_mid | 16 bits | ৬০-বিট টাইমস্ট্যাম্পের মধ্যবর্তী ১৬-বিট ক্ষেত্র |
| time_hi_and_version | 16 bits | ৬০-বিট টাইমস্ট্যাম্পের শীর্ষ ১২ বিট এবং ৪-বিট সংস্করণ নম্বর (সর্বদা <code>1</code>) |
| clock_seq_hi_res | 8 bits | ২-বিট RFC 4122 ভেরিয়েন্ট মার্কারের সাথে যুক্ত ৬-বিট ক্লক সিকোয়েন্স উচ্চ ক্ষেত্র |
| clock_seq_low | 8 bits | ক্লক সিকোয়েন্সের নিচের ৮ বিট |
| node | 48 bits | ৪৮-বিট নোড শনাক্তকারী — সাধারণত তৈরিকারী নেটওয়ার্ক ইন্টারফেসের MAC অ্যাড্রেস, অথবা MAC পাওয়া না গেলে একটি র্যান্ডম ৪৮-বিট মান |
ক্লক সিকোয়েন্স ক্ষেত্র (clock_seq_hi_res + clock_seq_low) হলো একটি ১৪-বিট কাউন্টার। সিস্টেম ঘড়ি পিছিয়ে গেলে (যেমন NTP সমন্বয়) বা শেষ পরিচিত টাইমস্ট্যাম্প সংরক্ষণ না করে সিস্টেম পুনরায় চালু হলে এটি বৃদ্ধি পায়। এটি নিশ্চিত করে যে ঘড়ি একঘেয়েভাবে না বাড়লেও নকল UUID তৈরি হবে না।
UUID v1 টাইমস্ট্যাম্প ডিকোড করা
৬০-বিট টাইমস্ট্যাম্প UUID-এর তিনটি ক্ষেত্রে ছড়িয়ে আছে। তৈরির সময় পুনর্গঠন করতে:
time_low(বাইট ০–৩),time_mid(বাইট ৪–৫), এবংtime_hi(বাইট ৬–৭, সংস্করণ নিবল বাদে) বের করুন- পুনর্গঠন করুন:
(time_hi << 48) | (time_mid << 32) | time_low - ফলাফল হলো ১৫৮২ সালের ১৫ অক্টোবর (গ্রেগরিয়ান ক্যালেন্ডার যুগ) থেকে
১০০-ন্যানোসেকেন্ড ব্যবধানের৬০-বিট গণনা - গ্রেগরিয়ান-থেকে-Unix অফসেট বিয়োগ করুন: ১২২,১৯২,৯২৮,০০০,০০০,০০০ (১৫৮২ সালের ১৫ অক্টোবর থেকে ১৯৭০ সালের ১ জানুয়ারির মধ্যে ১০০-ns ব্যবধান)
- ১০০-ন্যানোসেকেন্ড ব্যবধান থেকে মিলিসেকেন্ডে রূপান্তরের জন্য
১০,০০০দিয়ে ভাগ করুন - ফলাফলটি Date অবজেক্ট তৈরির জন্য
Unix মিলিসেকেন্ড টাইমস্ট্যাম্পহিসেবে ব্যবহার করুন - মানুষের পাঠযোগ্য আউটপুটের জন্য
ISO 8601ফরম্যাটে উপস্থাপন করুন
টাইমস্ট্যাম্পের নির্ভুলতা ১০০ ন্যানোসেকেন্ড — UUID v7-এর মিলিসেকেন্ড নির্ভুলতার চেয়ে অনেক বেশি সূক্ষ্ম। তবে বাস্তবে বেশিরভাগ অপারেটিং সিস্টেম সাব-মিলিসেকেন্ড ক্লক রেজোলিউশন প্রকাশ করে না, তাই নিচের বিটগুলো প্রায়ই শূন্য বা কৃত্রিমভাবে তৈরি হয়।
গোপনীয়তার ঝুঁকি
UUID v1-এর সবচেয়ে উল্লেখযোগ্য অসুবিধা হলো এটি নোড ক্ষেত্রে তৈরিকারী হোস্টের MAC অ্যাড্রেস এমবেড করে। এর মানে প্রতিটি UUID v1-এ যে মেশিন এটি তৈরি করেছে তার একটি স্থায়ী, বৈশ্বিকভাবে অনন্য পরিচয় বহন করে।
যে আক্রমণকারী UUID v1 পায় সে আনুমানিক তৈরির সময় এবং তৈরিকারী হোস্টের MAC অ্যাড্রেস জানতে পারে।
এই কারণে, আপনি এই তথ্য প্রকাশে স্বাচ্ছন্দ্যবোধ না করলে UUID v1 কখনো পাবলিক-মুখী শনাক্তকারী হিসেবে (যেমন URL বা API রেসপন্সে) ব্যবহার করা উচিত নয়। RFC 4122 নিজেই উল্লেখ করে যে একটি সিস্টেম MAC অ্যাড্রেসের পরিবর্তে র্যান্ডম ৪৮-বিট মান ব্যবহার করতে পারে, তবে অনেক বাস্তবায়ন তা করে না।
UUID v1 এখনো কোথায় উপযুক্ত
UUID v1 বনাম UUID v7
UUID v7 হলো সময়-ক্রমানুসারী শনাক্তকারীর জন্য UUID v1-এর আধুনিক উত্তরসূরি। এখানে একটি সরাসরি তুলনা করা হয়েছে:
| দিক | UUID v1 | UUID v7 |
|---|---|---|
| যুগ / সময় ভিত্তি | গ্রেগরিয়ান যুগ (১৫ অক্টোবর, ১৫৮২) | Unix যুগ (১ জানুয়ারি, ১৯৭০) |
| নির্ভুলতা | ১০০ ন্যানোসেকেন্ড | ১ মিলিসেকেন্ড |
| নোড শনাক্তকারী | MAC অ্যাড্রেস (হোস্ট পরিচয় ফাঁস করে) | র্যান্ডম (প্রাইভেট) |
| গোপনীয়তা | MAC অ্যাড্রেস ও তৈরির টাইমস্ট্যাম্প ফাঁস করে | কোনো হোস্ট তথ্য এমবেড নেই |
| DB ইন্ডেক্স পারফরম্যান্স | ভালো — প্রতি হোস্টে ক্রমানুসারী | চমৎকার — সব জেনারেটর জুড়ে k-sortable |
| মান | RFC 4122 (2005) | RFC 9562 (2024) |
নতুন প্রজেক্টে UUID v7 হলো UUID v1-এর সঠিক প্রতিস্থাপন। এটি আরও ভালো বৈশ্বিক সাজানোর ক্রম প্রদান করে — শুধু প্রতি হোস্টে ক্রমানুসারী নয়, সব জেনারেটর জুড়ে k-sortable — এবং কোনো MAC অ্যাড্রেস ফাঁস নেই।
কোড উদাহরণ
UUID v1 ব্রাউজারের বিল্ট-ইন API-তে নেই, তবে crypto.getRandomValues() ও Date.now() থেকে এটি তৈরি করা যায়। Python-এর uuid মডিউলে এটি সরাসরি আছে; Go-তে github.com/google/uuid প্যাকেজ প্রয়োজন:
// Generate a UUID v1 using the Web Crypto API
function generateUuidV1() {
const buf = new Uint8Array(16)
crypto.getRandomValues(buf)
const ms = BigInt(Date.now())
const gregorianOffset = 122192928000000000n
const t = ms * 10000n + gregorianOffset
const tLow = Number(t & 0xFFFFFFFFn)
const tMid = Number((t >> 32n) & 0xFFFFn)
const tHiVer = Number((t >> 48n) & 0x0FFFn) | 0x1000 // version 1
const clockSeq = (buf[8] & 0x3F) | 0x80 // variant 10xxxxxx
const clockSeqLow = buf[9]
const hex = (n, pad) => n.toString(16).padStart(pad, '0')
const node = [...buf.slice(10)].map(b => b.toString(16).padStart(2, '0')).join('')
return `${hex(tLow,8)}-${hex(tMid,4)}-${hex(tHiVer,4)}-${hex(clockSeq,2)}${hex(clockSeqLow,2)}-${node}`
}
// Extract the embedded timestamp from a UUID v1
function extractTimestamp(uuid) {
const parts = uuid.split('-')
const tHex = parts[2].slice(1) + parts[1] + parts[0]
const t = BigInt('0x' + tHex)
const ms = (t - 122192928000000000n) / 10000n
return new Date(Number(ms))
}
const id = generateUuidV1()
console.log(id) // e.g. "1eb5e8b0-6b4d-11ee-9c45-a1f2b3c4d5e6"
console.log(extractTimestamp(id)) // e.g. 2023-10-15T12:34:56.789Zimport uuid from datetime import datetime, timezone # Generate UUID v1 (uses MAC address by default) uid = uuid.uuid1() print(uid) # Extract embedded timestamp # uuid.time is 100-ns intervals since Oct 15, 1582 GREGORIAN_OFFSET = 122192928000000000 # 100-ns intervals ts_100ns = uid.time ts_ms = (ts_100ns - GREGORIAN_OFFSET) // 10000 dt = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc) print(dt.isoformat()) # e.g. "2023-10-15T12:34:56.789000+00:00"
package main
import (
"fmt"
"time"
"github.com/google/uuid" // go get github.com/google/uuid
)
func main() {
id, _ := uuid.NewUUID() // UUID v1
fmt.Println(id)
// Extract timestamp from UUID v1
// uuid.Time is 100-ns ticks since Oct 15, 1582
t := id.Time()
sec := int64(t)/1e7 - 12219292800 // convert to Unix seconds
nsec := (int64(t) % 1e7) * 100
ts := time.Unix(sec, nsec).UTC()
fmt.Println(ts.Format(time.RFC3339Nano))
}