ข้ามไปยังเนื้อหา

เครื่องมือสร้าง ULID - สร้าง ID ที่เรียงลำดับได้แบบไม่ซ้ำกันออนไลน์ฟรี

เครื่องมือสร้าง ULID ฟรีที่สร้าง ID ที่ไม่ซ้ำกันและเรียงลำดับได้อย่างทันที สร้าง ULID ที่ปลอดภัยทางคริปโตกราฟีสำหรับฐานข้อมูล API และระบบกระจายออนไลน์

เครื่องมือสร้าง ULID

กรอกค่าเพื่อดูผลลัพธ์
เครื่องคำนวณโหลด...
📚

เอกสารประกอบการใช้งาน

ULID คืออะไร?

ULID (ตัวระบุที่ไม่ซ้ำกันในระดับสากลและเรียงลำดับตามพจนานุกรมได้) คือรหัสยาว 26 อักขระที่ใช้กำกับระเบียนในฐานข้อมูลหรือเหตุการณ์ในระบบแบบกระจาย รหัสดังกล่าวรวมเวลาปัจจุบันเข้ากับข้อมูลสุ่ม ดังนั้นรายการ ULID ที่เรียงตามตัวอักษรจึงเรียงตามเวลาที่สร้างแต่ละรายการด้วย ตัวสร้าง ULID คือเครื่องมือที่สร้างรหัสเหล่านี้

โครงสร้าง ULID

ULID มีสองส่วน เขียนต่อกันโดยไม่มีตัวคั่น

  • ตราประทับเวลา (10 อักขระ): จำนวนมิลลิวินาทีตั้งแต่ 1 มกราคม ค.ศ. 1970 (จุดเริ่มต้นยุค Unix) ครอบคลุมได้สูงสุด 48 บิต
  • ข้อมูลสุ่ม (16 อักขระ): ข้อมูลสุ่ม 80 บิต ซึ่งเพิ่มเข้ามาเพื่อให้ ULID สองรายการที่สร้างในมิลลิวินาทีเดียวกันยังคงแตกต่างกันได้เกือบแน่นอน

ทั้งสองส่วนเขียนโดยใช้อักขระ Base32 ของ Crockford ได้แก่ ตัวเลข 0–9 และตัวอักษร A-Z ยกเว้น I, L, O และ U ตัวอักษรทั้งสี่นี้ถูกตัดออกเพราะอาจสับสนกับตัวเลข 0 และ 1 หรือสับสนกันเอง ผลลัพธ์จึงเป็นสตริงที่สั้น อ่านออกเสียงได้ง่าย และใส่ใน URL ได้โดยตรงอย่างปลอดภัย

วิธีคำนวณ ULID

ตัวสร้าง ULID สร้างตัวระบุในสามขั้นตอน

  1. อ่านเวลาปัจจุบัน เป็นมิลลิวินาทีตั้งแต่จุดเริ่มต้นยุค Unix ค่านี้เป็นตัวเลขขนาด 48 บิต
  2. สร้างข้อมูลสุ่ม 80 บิต โดยปกติใช้ตัวสร้างเลขสุ่มที่ปลอดภัยทางคริปโตกราฟี ทำให้ได้ไบต์สุ่ม 10 ไบต์
  3. เข้ารหัสทั้งสองส่วนแยกกัน โดยใช้อักขระ Base32 ของ Crockford: ตราประทับเวลา 48 บิตกลายเป็นอักขระ 10 ตัว และค่าสุ่ม 80 บิตกลายเป็นอักขระ 16 ตัว จากนั้นนำสตริงที่เข้ารหัสแล้วทั้งสองส่วนมาต่อกันเป็น ULID ยาว 26 อักขระ

การเข้ารหัสทำโดยอ่านตัวเลขครั้งละ 5 บิต เนื่องจากอักขระ Base32 แต่ละตัวแทนค่าที่เป็นไปได้หนึ่งค่าใน 32 ค่า (2^5 = 32) อักขระสิบตัวเก็บได้สูงสุด 50 บิต ซึ่งเพียงพอสำหรับตราประทับเวลา 48 บิต อักขระสิบหกตัวเก็บได้พอดี 80 บิต ซึ่งตรงกับส่วนข้อมูลสุ่มโดยไม่มีบิตเหลือ

ตัวอย่างพร้อมวิธีทำ

สมมติว่าตัวสร้าง ULID ทำงานที่ตราประทับเวลา 1712345678901 (มิลลิวินาทีตั้งแต่จุดเริ่มต้นยุค Unix) และสุ่มได้ไบต์ [12, 240, 88, 3, 199, 45, 6, 231, 128, 17]

ขั้นตอน 1 – เข้ารหัสตราประทับเวลา หาร 1712345678901 ด้วย 32 ซ้ำ ๆ โดยเก็บเศษที่ได้ในแต่ละครั้ง แล้วอ่านตัวเลขจากตัวสุดท้ายไปตัวแรก (นี่คือการแปลงเลขฐานตามมาตรฐาน) ผลลัพธ์คือสตริงยาว 10 อักขระ 01HTQW311N

ขั้นตอน 2 – เข้ารหัสข้อมูลสุ่ม รวมไบต์สุ่ม 10 ไบต์เป็นกระแสบิตขนาด 80 บิต จากนั้นอ่านครั้งละ 5 บิต และแปลงแต่ละกลุ่มขนาด 5 บิตเป็นอักขระ Base32 ผลลัพธ์คือสตริงยาว 16 อักขระ 1KR5G0Y75M3EF00H

ขั้นตอน 3 – นำส่วนต่าง ๆ มาต่อกัน ULID สุดท้ายคือ:

101HTQW311N 1KR5G0Y75M3EF00H
2

เขียนโดยไม่มีช่องว่าง: 01HTQW311N1KR5G0Y75M3EF00H รวมทั้งหมด 26 อักขระ

การใช้ตัวสร้างนี้

ตัวสร้างทำงานในเบราว์เซอร์ ULID แต่ละรายการสร้างจากนาฬิกาของเบราว์เซอร์และบิตสุ่มใหม่ 80 บิตที่ได้จากตัวสร้างเลขสุ่มทางคริปโตกราฟีของเบราว์เซอร์ ดังนั้นจึงไม่มีการส่งหรือดึงตัวระบุใดจากเซิร์ฟเวอร์

  • จำนวน ULID รับจำนวนเต็มตั้งแต่ 1 ถึง 50 ค่าเริ่มต้นคือ 1
  • สร้าง ULID สร้างชุดใหม่ การเปลี่ยนจำนวนก็สร้างชุดใหม่เช่นกัน
  • คัดลอก บนผลลัพธ์จะคัดลอก ULID รายการนั้นเพียงรายการเดียว เมื่อแสดงมากกว่าหนึ่งรายการ คัดลอกทั้งหมด จะคัดลอกรายการทั้งหมด โดยมี ULID หนึ่งรายการต่อบรรทัด
  • รีเซ็ต ตั้งจำนวนกลับเป็น 1 และสร้าง ULID ใหม่หนึ่งรายการ

ใต้ผลลัพธ์ แผงโครงสร้าง ULID จะแยก ULID รายการแรกในชุดออกเป็นสองส่วน ได้แก่ 10 อักขระแรก (ตราประทับเวลา) และ 16 อักขระสุดท้าย (ข้อมูลสุ่ม)

ULID เทียบกับ UUID

คุณลักษณะULIDUUID (เวอร์ชัน 4)
ความยาว26 อักขระ36 อักขระ (มีขีดกลาง)
เรียงตามเวลาที่สร้างได้ใช่ไม่
การเข้ารหัสCrockford Base32ฐานสิบหก
มีตราประทับเวลามี (48 บิต)ไม่
ปลอดภัยสำหรับ URL โดยไม่ต้องทำการหลีกอักขระใช่ใช่

รูปแบบทั้งสองมีเป้าหมายเพื่อสร้างตัวระบุที่ไม่ซ้ำกันในระบบต่าง ๆ โดยไม่ต้องมีหน่วยงานกลางแจกหมายเลข ความแตกต่างในทางปฏิบัติที่สำคัญคือการเรียงลำดับ เนื่องจาก ULID เริ่มต้นด้วยตราประทับเวลา การเรียง ULID เป็นข้อความธรรมดาจึงเรียงตามเวลาไปด้วย UUID แบบสุ่มไม่มีคุณสมบัตินี้ เพราะทุกส่วนของ UUID เป็นข้อมูลสุ่ม

การใช้งานทั่วไป

  • คีย์หลักของฐานข้อมูล: ULID ช่วยให้ฐานข้อมูลทำดัชนีแถวใหม่ได้โดยประมาณตามลำดับที่แทรกเข้าไป ซึ่งกลไกฐานข้อมูลจำนวนมากจัดการได้มีประสิทธิภาพกว่าคีย์ที่สุ่มทั้งหมด
  • ระบบแบบกระจาย: เซิร์ฟเวอร์แยกกันสามารถสร้าง ULID ได้อย่างอิสระโดยไม่ต้องประสานงานกับตัวนับส่วนกลาง และผลลัพธ์ยังคงไม่ซ้ำกันได้เกือบแน่นอน
  • บันทึกเหตุการณ์: เนื่องจาก ULID เรียงตามเวลา รายการรหัสเหตุการณ์จึงใช้เป็นลำดับเวลาโดยประมาณได้
  • ตัวระบุ API และไฟล์: รูปแบบที่มีความยาวคงที่ 26 อักขระและปลอดภัยสำหรับ URL ทำงานได้อย่างเหมาะสมในที่อยู่เว็บและชื่อไฟล์

รูปแบบตัวระบุที่เกี่ยวข้อง ได้แก่ KSUID ซึ่งเข้ารหัสตราประทับเวลาเพื่อใช้เรียงลำดับเช่นกัน และรหัส Snowflake ที่ Twitter และหน่วยงานอื่นใช้ โดยรวมตราประทับเวลา ตัวระบุเครื่อง และตัวนับเข้าด้วยกัน

ตัวอย่างโค้ด

ตัวอย่างแต่ละรายการด้านล่างสร้าง ULID ด้วยวิธีเดียวกับที่ข้อกำหนด ULID อธิบายไว้ ได้แก่ เข้ารหัสตราประทับเวลา 48 บิตเป็นอักขระ Crockford Base32 10 ตัว เข้ารหัสข้อมูลสุ่ม 80 บิตเป็นอักขระเพิ่มอีก 16 ตัว แล้วนำมาต่อกัน

JavaScript

1const ENCODING_CHARS = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
2
3function encodeULID(time, randomBytes) {
4  // Timestamp: 48 bits -> 10 characters
5  let timestampStr = '';
6  let t = time;
7  for (let i = 0; i < 10; i++) {
8    timestampStr = ENCODING_CHARS[t % 32] + timestampStr;
9    t = Math.floor(t / 32);
10  }
11
12  // Randomness: 80 bits -> 16 characters
13  let result = timestampStr;
14  let bits = 0;
15  let bitCount = 0;
16  for (let i = 0; i < 10; i++) {
17    bits = (bits << 8) | randomBytes[i];
18    bitCount += 8;
19    while (bitCount >= 5) {
20      bitCount -= 5;
21      result += ENCODING_CHARS[(bits >> bitCount) & 0x1f];
22    }
23  }
24  return result;
25}
26
27function generateULID() {
28  const randomBytes = crypto.getRandomValues(new Uint8Array(10));
29  return encodeULID(Date.now(), randomBytes);
30}
31
32console.log(generateULID());
33

Python

1import os
2import time
3
4ENCODING_CHARS = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
5
6def encode_ulid(time_ms, random_bytes):
7    # Timestamp: 48 bits -> 10 characters
8    chars = []
9    t = time_ms
10    for _ in range(10):
11        chars.append(ENCODING_CHARS[t % 32])
12        t //= 32
13    timestamp_part = "".join(reversed(chars))
14
15    # Randomness: 80 bits -> 16 characters
16    bits = 0
17    bit_count = 0
18    random_part = []
19    for byte in random_bytes:
20        bits = (bits << 8) | byte
21        bit_count += 8
22        while bit_count >= 5:
23            bit_count -= 5
24            random_part.append(ENCODING_CHARS[(bits >> bit_count) & 0x1F])
25
26    return timestamp_part + "".join(random_part)
27
28def generate_ulid():
29    return encode_ulid(int(time.time() * 1000), os.urandom(10))
30
31print(generate_ulid())
32

Java

1import java.security.SecureRandom;
2import java.time.Instant;
3
4public class ULIDGenerator {
5    private static final SecureRandom random = new SecureRandom();
6    private static final char[] ENCODING_CHARS =
7        "0123456789ABCDEFGHJKMNPQRSTVWXYZ".toCharArray();
8
9    public static String generateULID() {
10        long timestamp = Instant.now().toEpochMilli();
11        byte[] randomBytes = new byte[10];
12        random.nextBytes(randomBytes);
13
14        // Timestamp: 48 bits -> 10 characters
15        char[] timestampChars = new char[10];
16        long t = timestamp;
17        for (int i = 9; i >= 0; i--) {
18            timestampChars[i] = ENCODING_CHARS[(int) (t % 32)];
19            t /= 32;
20        }
21
22        // Randomness: 80 bits -> 16 characters
23        StringBuilder result = new StringBuilder(new String(timestampChars));
24        long bits = 0;
25        int bitCount = 0;
26        for (byte b : randomBytes) {
27            bits = (bits << 8) | (b & 0xFF);
28            bitCount += 8;
29            while (bitCount >= 5) {
30                bitCount -= 5;
31                result.append(ENCODING_CHARS[(int) ((bits >> bitCount) & 0x1F)]);
32            }
33        }
34        return result.toString();
35    }
36
37    public static void main(String[] args) {
38        System.out.println(generateULID());
39    }
40}
41

คำถามที่พบบ่อย

ULID ใช้ทำอะไร ULID ใช้เป็นตัวระบุที่ไม่ซ้ำกันสำหรับแถวในฐานข้อมูล ทรัพยากร API หรือเหตุการณ์ที่บันทึกไว้ ในกรณีที่การเรียงตามเวลาที่สร้างมีประโยชน์ด้วย

ULID ยาวเท่าใด ULID มีความยาว 26 อักขระเสมอ โดยมี 10 อักขระสำหรับตราประทับเวลา และ 16 อักขระสำหรับส่วนข้อมูลสุ่ม

ULID ใช้การเข้ารหัสแบบใด ULID ใช้อักขระ Base32 ของ Crockford ซึ่งประกอบด้วยตัวเลข 0–9 และตัวอักษร A-Z โดยนำ I, L, O และ U ออกเพื่อป้องกันความสับสนกับอักขระอื่น

ULID แตกต่างจาก UUID อย่างไร ULID เรียงตามเวลาที่สร้างและมีความยาว 26 อักขระ UUID แบบสุ่ม (เวอร์ชัน 4) ไม่เรียงตามเวลาและมีความยาว 36 อักขระเมื่อรวมยัติภังค์

โอกาสที่ ULID สองรายการจะชนกันมีมากเพียงใด ข้อมูลสุ่ม 80 บิตทำให้โอกาสชนกันต่ำมาก ต้องสร้าง ULID ประมาณ 1.3 ล้านล้านรายการภายในมิลลิวินาทีเดียวกัน จึงจะมีโอกาส 50% ที่ ULID สองรายการใด ๆ จะตรงกัน

สร้าง ULID โดยไม่เชื่อมต่ออินเทอร์เน็ตได้หรือไม่ ได้ ULID ต้องใช้เพียงนาฬิกาในเครื่องและตัวสร้างเลขสุ่ม จึงสร้างได้ทั้งหมดแบบออฟไลน์

เอกสารอ้างอิง

  1. "ULID Specification." GitHub, https://github.com/ulid/spec.
  2. "Crockford's Base32 Encoding." http://www.crockford.com/base32.html.