TypeID - ตัวระบุเฉพาะส่วนกลางแบบ type-safe ที่จัดเรียงแบบ K-sortable ได้ ซึ่งได้แรงบันดาลใจจาก Stripe ID
(github.com/jetpack-io)- TypeID คือรูปแบบตัวระบุเฉพาะส่วนกลางที่ขยายจาก UUIDv7 ให้มีความปลอดภัยด้านชนิดข้อมูล โดยได้แรงบันดาลใจจากวิธีใช้ prefix ของ Stripe API
- สตริงตามรูปแบบมาตรฐานประกอบด้วย 3 ส่วน ได้แก่ type prefix แบบ ASCII
snake_caseตัวพิมพ์เล็กยาวได้สูงสุด 63 ตัวอักษร, ตัวคั่น_, และ suffix UUIDv7 ยาว 26 ตัวอักษรที่เข้ารหัสด้วย base32 แบบดัดแปลง - type prefix ช่วยป้องกันการนำ ID ของ
userไปใช้ผิดที่ซึ่งควรเป็น ID ของpostและยังช่วยให้ระบุได้ทันทีระหว่างดีบักว่าตัวระบุนั้นชี้ไปยังเอนทิตีประเภทใด - TypeID เป็น superset ของ UUID โดยเมื่อลบข้อมูลประเภทออกและถอดรหัส จะได้ UUIDv7 ที่ถูกต้อง
- สามารถจัดเรียงแบบ K-sortable ได้ จึงใช้เป็นคีย์หลักของฐานข้อมูลได้ และมีเป้าหมายเพื่อลดปัญหา database locality ที่แย่ลงเมื่อเทียบกับ UUIDv4 ซึ่งเป็น global ID แบบสุ่มทั้งหมด
- การเข้ารหัสแบบ base32 มีข้อดีคือปลอดภัยต่อ URL, ไม่แยกความต่างตัวพิมพ์เล็กใหญ่, หลีกเลี่ยงอักขระที่กำกวม, ดับเบิลคลิกเพื่อเลือกได้, และมีความยาวสั้นกว่าการเข้ารหัสแบบ hex ตามธรรมเนียมของ UUID
- มี implementation อย่างเป็นทางการสำหรับ Go, SQL, TypeScript และสเปกล่าสุดคือ v0.3.0
- สามารถใช้เครื่องมือบรรทัดคำสั่งเพื่อสร้าง TypeID, ถอดรหัส UUID จาก TypeID ที่มีอยู่, และเข้ารหัส UUID เป็น TypeID ได้
typeid new prefixใช้สร้าง TypeID ใหม่typeid decode prefix_01h2xcejqtf2nbrexx3vqjhp41จะแสดง type และ uuidtypeid encode prefix 0188bac7-4afa-78aa-bc3b-bd1eef28d881ใช้สร้าง TypeID
- ใน TypeID Converter ของ Jetify สามารถแปลงสตริง TypeID เป็น UUID หรือแปลงเป็น TypeID จากรูปแบบ
prefix:UUIDได้
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
มีข้อเสนอแนะอยู่หลายอย่าง: ควรกำหนดและทำเอกสารของ สตริง prefix ให้ชัดเจนตั้งแต่เนิ่น ๆ ก่อนที่จะสายเกินไป
ดูจาก implementation ของ Go แล้วใช้ ASCII ตัวพิมพ์เล็กจึงน่าจะโอเค แต่สำหรับชนิดแบบผสมอย่าง
article-commentยังดูคลุมเครือในโปรเจกต์ที่ซับซ้อนหรือ ORM มักเลี่ยงตัวคั่นได้ยาก จึงน่าพิจารณาให้รองรับตัวคั่นแบบเดี่ยว
implementation ของ Go ยังไม่มีการทดสอบ ทั้งที่เป็นโค้ดที่เขียน unit test ได้ง่าย จึงควรเพิ่มอย่างยิ่ง
ใน Go น่าจะเหมาะกว่าที่จะใช้ฟังก์ชัน parse ที่ถูกต้องและใช้อาร์เรย์ไบต์ภายในแบบเดียวกับ implementation UUID ของ Google ส่วนสตริงก็ควรใช้เฉพาะตอนเรนเดอร์และกับ prefix
ตอนนี้การ parse ผ่อนปรนเกินไป และถ้า suffix ว่างก็ดูเหมือนจะเข้าสู่โหมดสร้างใหม่ อีกทั้งการ index หลัง
SplitNก็น่าจะ panic ได้ถ้าไม่มีขีดล่างแต่พอดูจากภาพรวมแล้ว แม้จะพยายามหาจุดตำหนิในดีไซน์ สุดท้ายก็รู้สึกว่ามันหาจุดลงตัวของ sweet spot ของ trade-off ได้ดี
ถึงอย่างนั้น ข้อท้วงติงก็ถูกต้อง และยิ่งมี implementation หลายภาษาเพิ่มขึ้น ก็ยิ่งต้องตรวจสอบความเข้ากันได้ระหว่างกัน จึงมีแผนจะเพิ่มชุดทดสอบที่เข้มงวดยิ่งขึ้น
ส่วนเรื่อง prefix อยากรู้ว่าความกังวลคือการที่ยังไม่ได้กำหนดชุดอักขระที่อนุญาตไว้ในสเปกหรือไม่
และได้ทำให้ prefix ในสเปกชัดเจนขึ้นแล้วด้วย
จริง ๆ แล้ว prefix เป็นสิ่งที่กำหนดตามโดเมนการใช้งาน
ใช้วิธีแบบนี้มาหลายปีแล้ว แต่มีสองจุดที่ต่างกัน
อย่างแรกคือไม่ได้มองว่าคนจะพิมพ์ค่านี้ด้วยมือจริง ๆ จึงไม่ได้กังวลมากเรื่องความสับสนระหว่าง
lกับ1แต่แทนที่จะเป็นแบบนั้น จะใช้ base32 ที่ตัดสระ
eiouออก เพื่อลดโอกาสที่บังเอิญกลายเป็นคำ โดยเฉพาะคำหยาบอย่างที่สองคือจะเพิ่มอักขระ base32 ที่ใส่ salt แล้วสองตัวเป็น checksum
เวลาค่าผิดปกติไม่ว่าจะเกิดจากความผิดพลาดหรือเจตนาร้าย ก็ไม่จำเป็นต้องไป query ถึง data store และไม่เข้าใจว่าทำไม implementation อื่น ๆ ถึงไม่ทำแบบนี้
analritaแล้วมีคนร้องเรียนอาจควรพิจารณาใส่
aเข้าไปในชุดอักขระที่ตัดทิ้งด้วยถ้ามองว่าไม่ได้มีคนพิมพ์ด้วยมือจริง ๆ ก็สงสัยว่าเส้นทางไหนที่จะทำให้ใส่ค่าผิดโดยไม่ตั้งใจได้
อาจมีกรณี copy/paste ผิด หรือหน้าเว็บเรนเดอร์เป็นตัวพิมพ์ใหญ่ แต่ถ้าเป็น base32 ก็จัดรูปแบบตัวพิมพ์เล็กใหญ่ให้เป็นมาตรฐานได้
อีกอย่างคือ checksum 2 ไบต์ที่ไม่ปลอดภัยเชิงคริปโตจะช่วยอะไรได้อย่างไรในกรณีที่มีเจตนาร้าย
กำลังพิจารณาอยู่ว่าควรรวมไว้ในสเปกของ TypeID หรือไม่
ไม่แน่ใจว่าช่วยลดการ query ฐานข้อมูลไปได้มากแค่ไหน แต่ก็ดีตรงที่ระหว่างถอดรหัสจะไม่หลุดไปเป็นข้อผิดพลาดที่กำกวมกว่าเดิม
นอกเหนือจากเนื้อหาหลัก ยังมีลิงก์ “Crockford's alphabet”: https://www.crockford.com/base32.html
ระบบ base32 นี้ตัด
IกับLที่สับสนกับ1,Oที่สับสนกับ0และUออกไปจากตัวอักษรและตัวเลขในหน้านั้นบอกว่าเหตุผลที่ตัด
Uออกคือ “คำหยาบที่เกิดขึ้นโดยไม่ตั้งใจ” แต่ไม่เข้าใจว่าหมายถึงอะไรถ้าจะสร้างอักษร base32 ที่ใช้ตัวอักษรและตัวเลขซึ่งไม่ชวนสับสน แค่ตัด
O,I,Lออกก็พอแต่ก็ยังเหลือ 33 ตัวอยู่ จึงต้องตัดเพิ่มอีก 1 ตัว และจะเป็นตัวไหนก็ได้ เลยใส่เหตุผลแบบตามอำเภอใจให้กับตัวสุดท้ายที่ถูกตัดออก
ถ้าเป็น ID ที่ผู้ใช้มองเห็นได้ เหตุผลนี้ก็ไม่ได้เหลวไหลเสียทีเดียว แต่แน่นอนว่าไม่ได้ป้องกันได้สมบูรณ์เลย
IและOออกไปแล้ว ถ้าตัดUเพิ่มด้วย ก็จะลดชุดตัวอักษร 3 ตัวหรือ 4 ตัวที่ดูหยาบคายได้ค่อนข้างมากแน่นอนว่ายังมีบางชุดที่เป็นไปได้เพราะยังมี
Aอยู่ แต่โอกาสก็น้อยมากUเป็นตัวอักษรที่หยาบคายจนเกือบเข้าข่ายลามก เพราะในสมัยของ Cicero มันยังไม่มีอยู่ที่บริษัทก็เคยนิยาม “เลขฐาน” ใหม่หลายแบบสำหรับ QR code และส่วนตัวมองว่านี่เป็นพื้นที่ที่วิทยาการคอมพิวเตอร์ยังใช้ประโยชน์กันน้อย
ตอนนั้นกำลังแก้ปัญหา URL slug และเพราะมันค่อนข้างยาว จึงมองว่า 5 บิตต่อไบต์จะช่วยลดความลำบากในการคัดลอกเขียนตามได้
สุดท้ายเราพอมีพื้นที่ให้ตัดตัวอักษรออกเพิ่มอีกไม่กี่ตัว และหลังเลิกงานตอนที่ทุกคนกลับกันหมดแล้ว เราสองคนนั่งจัดอันดับระดับความดูหมิ่นของคำหยาบเพื่อเลือกว่าจะตัดตัวไหนออก
หลังจากนั้นผมก็โน้มน้าวว่าคำเหยียดน่าจะเป็นปัญหาใหญ่กว่า เลยหันไปเน้นการตัด
nแทนutggrก็แค่น่ารักดี แต่n**rนั้นหมายถึงต้องไปคุยอึดอัดกับทีม HR หลายทีมชุดอักขระสุดท้ายตอนนี้จำได้ลาง ๆ แต่โดยทั่วไปคือ
[a-z][0-9]และมีสัญลักษณ์จำนวนมากที่ใช้ใน URL ไม่ได้หรืออ่านบอกต่อกันได้ยากเท่าที่จำได้ เราตัด
0,l,1ออกทั้งหมด และน่าจะถือว่าการคัดลอกเขียนตามจะทำกันเป็นตัวพิมพ์ใหญ่ทั้งหมดหรือพิมพ์เล็กทั้งหมด0oไม่ใช่ปัญหา และ1Lก็เหมือนกันการเข้ารหัสแบบ Crockford ไม่ค่อยถูกใจผม
เวลาไปซัพพอร์ตหรือวิเคราะห์ค่าที่เข้ารหัสด้วยวิธีนี้จริง ๆ รู้สึกว่ามันเป็นความผิดพลาดที่เห็นได้ชัด
ตัวอักษรชุดนี้ถูกออกแบบมาสำหรับเป้าหมายที่ในความเป็นจริงพบไม่บ่อย เช่น การอ่านตัวระบุทางโทรศัพท์ และมันนำความกำกวมเข้ามา
ถ้าต้อง
grepในล็อกหรือเทียบข้ามระบบโดยอาศัยสตริงที่เข้ารหัสเอง มันคือหายนะ และการอนุญาตให้มีขีดกลางก็ยิ่งเป็นต้นเหตุหลักของปัญหาการคัดลอก/วางและการตัดบรรทัดการพิมพ์ object identifier ด้วยมือตรง ๆ นั้นไม่ค่อยเกิดขึ้น แต่การคัดลอก/วางข้ามแอป แชต และฟอรัม การส่งต่อทางอีเมล และการค้นหาในไฟล์ล็อกเป็นเรื่องปกติ
ในเงื่อนไขแบบนี้ ความอ่านออกเสียงได้แทบไม่มีความหมาย ความไม่แยกแยะตัวพิมพ์ใหญ่เล็กกลับเป็นอุปสรรค และสิ่งที่ต้องการคือความสม่ำเสมอกับความทนทานต่อการวางและการตัดบรรทัด
base58 เป็นการเข้ารหัสแบบหนึ่งต่อหนึ่งที่ตอบโจทย์นี้ได้ดีกว่าและยังสั้นกว่าอีกด้วย
โดยได้แรงบันดาลใจจาก Stripe ผมใช้ UUID ที่เข้ารหัสแบบ base58 พร้อม type prefix เป็น object identifier มาหลายปีแล้ว เช่น
user_1BzGURpnHGn6oNru84B3Riแต่ก็ต้องยอมรับว่า base32 ของ Douglas Crockford ถูกออกแบบไว้เมื่อ 20 ปีก่อน ในยุคที่สภาพแวดล้อมการใช้งานแตกต่างจากตอนนี้มาก
แต่เพราะไม่อยากตั้งอยู่บนสมมติฐานว่าต้องแยกตัวพิมพ์ใหญ่เล็ก สุดท้ายเลยเอนเอียงมาทาง base32
ตัวอย่างเช่น คุณอาจอยากใช้ ID เป็นชื่อไฟล์ และอาจอยู่ในสภาพแวดล้อมที่ติดข้อจำกัดของระบบไฟล์แบบไม่แยกตัวพิมพ์ใหญ่เล็ก
TypeID ใช้อักษร Crockford แบบตัวพิมพ์เล็กเสมอ ไม่ได้ใช้กฎการเข้ารหัสของ Crockford ทั้งหมด
TypeID ไม่อนุญาตให้มีขีดกลาง และไม่ยอมให้เข้ารหัส ID เดียวกันได้หลายแบบด้วยการใช้ตัวอักษรที่กำกวมสลับกัน
แต่บางครั้งก็มีกรณีที่ต้องพิมพ์เองจากตัวระบุในภาพหน้าจอหรือการแชร์หน้าจอ หรือจากอุปกรณ์อีกเครื่องที่ดึงตัวระบุออกมาได้ไม่ง่าย
Crockford base32 ก็ใช้งานได้ แต่ไม่ถึงกับชอบมากนัก
ส่วนตัวแล้วตัวเลือกอันดับหนึ่งคือใช้ KSUID ที่มี type prefix
จะได้ ID แบบ 160 บิตที่จัดเรียงแบบ K-sortable ได้ในรูปแบบ base62 และถ้าไม่ได้จำเป็นต้องใช้ ID 128 บิตเพราะเหตุผลด้านความเข้ากันได้ ก็ถือว่าเหมาะดี
base32 ที่ผมชอบคือ z-base-32 เพราะรู้สึกว่าสบายตากว่า: https://philzimmermann.com/docs/human-oriented-base-32-encod...
ปัญหาใหญ่ที่สุดของ base58 คือมันเหมาะกับจำนวนเต็ม แต่เหมาะน้อยกว่าสำหรับข้อมูลไบนารีแบบสุ่มอย่างกุญแจเข้ารหัส และสตริงที่แยกตัวพิมพ์ใหญ่เล็กก็ดูไม่ค่อยสวย
เรียบดี
ชอบ prefix แบบ “type-safe”
ใน ORM ของเราเคยใช้วิธีคล้ายกัน โดยติดแท็กกับ integer ID ใน DB ตามประเภทเอนทิตีโดยอัตโนมัติ และเรียกมันว่า tagged ids: https://joist-orm.io/docs/advanced/tagged-ids
เราใช้
:เป็นตัวคั่น แต่ก็แอบเสียดายอยู่นิดหน่อยที่ไม่ได้ใช้_ในแง่ของการคัดลอก/วางด้วยการดับเบิลคลิกในทางทฤษฎี การให้ Joist แปลง “UUID column ใน DB” ให้เป็น “TypeID ในโดเมนโมเดล” ก็น่าจะทำได้ง่ายมาก แต่ตอนนี้คงยังทำไม่ได้ด้วยการตั้งค่าในฝั่งผู้ใช้อย่างเดียว
ถึงอย่างนั้นก็ยังเป็นไอเดียที่ดี
ID ขององค์ประกอบจะมีรูปแบบอย่าง
t3_15bfi0โดยt3_คือ type prefixt3คือโพสต์,t1คือคอมเมนต์,t5คือซับเรดดิต และส่วนที่เหลือคือการเข้ารหัส base36 ของ primary key แบบเพิ่มอัตโนมัติ.)colon จะถูก
%-encode ใน URL ทำให้ ID ยาวขึ้น และ URL ทั้งดูน่าเกลียดทั้งยาวจนน่ารำคาญมากUUIDv7 เป็นของฮิตบน HN มาหลายปีแล้ว เลยสงสัยว่าเมื่อไรจะกลายเป็นมาตรฐานจริงจังเสียที และเมื่อไรไลบรารี, ฐานข้อมูล และ ecosystem ที่เหลือจะรองรับแบบ native
ซอฟต์แวร์ส่วนใหญ่ไม่ได้สนใจ specific bit ภายใน UUID ดังนั้นจะใช้ตั้งแต่วันนี้เลยก็ได้
ถ้ามีซอฟต์แวร์ที่สนใจ bit เหล่านั้น ก็แค่ทำตัวให้เหมือน UUIDv4 ได้ และ bit แบบนั้นก็สุ่มออกมาได้อยู่แล้ว
ถ้าต้องมีขั้นตอนการสร้างเฉพาะ ก็เขียนเองได้และไม่ได้ยากอะไร
ยกตัวอย่าง ผมดูแล Dart UUID library อยู่ ซึ่งใน beta major release ล่าสุดมี v6, v7 และ custom v8 รวมอยู่ด้วย
น่าจะมีรายการ implementation อยู่ที่ไหนสักแห่ง และผมก็อยู่ในหน้านั้นในรายชื่อผู้ดูแลไลบรารี เลยได้รับการแจ้งจากผู้เขียนทุกครั้งที่มีร่างใหม่ออกมา
ชอบตรงที่บอกว่า “สามารถคัดลอก/วางด้วยการดับเบิลคลิกได้”
รายละเอียดเล็กๆ สำคัญ
ผมมีปัญหากับ UUID อยู่นิดหน่อย
ไม่เข้าใจว่าทำไมต้องทำพิธีรีตองเรื่อง UUID versioning แทนที่จะเอา เวลา + ค่าสุ่ม มารวมกันเฉยๆ
ถ้า locality ไม่สำคัญ ก็ใช้เลขสุ่ม 128 บิตตรงๆ ไปเลยก็ได้
จากประสบการณ์ ดูเหมือนคนส่วนใหญ่จะคิดว่าต้องเก็บ UUID เป็นเลขฐาน 16 แบบอ่านได้โดยมนุษย์ แถมยังรวม hyphen เข้าไปด้วย
เปลืองพื้นที่ทั้งในฐานข้อมูล, เครือข่าย และหน่วยความจำมากเกินไป
อย่าง ULID https://github.com/ulid/spec ก็สั้นกว่าและเก็บเวลาไว้ด้วย จึงเรียงตามลำดับพจนานุกรมได้
แต่ความจริงก็เหมือนปัญหาทางวิศวกรรมอื่นๆ คือ เขียน requirement ออกมาแล้วดูว่าอะไรตอบโจทย์
การอ่านข้อดีของหลายๆ format มีประโยชน์ เพราะทำให้เราได้ใช้บทเรียนที่คนอื่นเรียนมาอย่างยากลำบากแล้ว
ความสามารถในการ sort ได้และ locality ตามเวลาอาจไม่ใช่สิ่งที่นึกถึงเองตามธรรมชาติ แต่ถ้าจำเป็น การรู้ไว้ก่อนย่อมดีกว่าเพิ่งมารู้ตอนอีก 4 ปีให้หลังว่าคุณทิ้งข้อมูลนั้นไปแล้ว
UUID บาง format ยังใส่ปัญหาด้านความปลอดภัยเล็กๆ เข้ามาเองด้วย เช่น การรั่วของ MAC address ใน UUID v1 ซึ่งควรหลีกเลี่ยง
ถ้า use case ของคุณเหมาะกับวิธีเดิมที่มีอยู่แล้ว ก็ใช้มันไปได้เลย
ถ้าไม่ใช่ ก็ไม่ต้องกังวลมาก
โดยส่วนตัว ในที่ที่ผมใช้ UUID มากที่สุด เราระบุไว้แค่ว่า “ส่ง unique string มาเถอะ จะใช้ UUID library อะไรก็ได้ถ้าคุณสบายใจ”
ระบบนี้ดูเหมือนจะมี format เฉพาะแตกต่างกันไปตามแหล่งข้อมูล แต่ก็ไม่เป็นไร
ปริมาณงานอยู่ระดับหลายหมื่นรายการต่อวัน เลยไม่ได้มีปัญหาเรื่องสเกล และก็ไม่จำเป็นต้อง sort ตาม UUID
มันไม่ใช่ identifier จริงๆ เท่าไร แต่เป็น token เฉพาะที่ผู้ส่งสร้างขึ้นมาสำหรับแต่ละข้อความ เพื่อใช้ตรวจจับการมาถึงซ้ำในปลายทางล่างของระบบ heterogeneous ที่มีหลายคิว
ไม่จำเป็นต้อง unique แบบ global ด้วยซ้ำ แค่ unique ภายใน shard เล็กๆ ก็พอ และตามหลักแล้วจะวนกลับมาซ้ำเมื่อเวลาผ่านไปก็ยังได้
เพียงแต่เพื่อความเรียบง่าย เราเลยคงระบบให้ unique ตลอดทั้งช่วงเวลาไปเลย
ถ้าสร้างเอง เราจะอ่านข้อมูลจาก
/dev/urandomแล้วเข้ารหัสเป็น base64 และเลือกขนาดที่ไม่ลงท้ายด้วย==อันนี้ก็ไม่ใช่เพราะปัญหาจริงอะไรหรอก แต่เพราะเหตุผลด้านความสวยงามล้วนๆ
ถึงอย่างนั้นก็ยังไม่เข้าใจอยู่ดีว่าทำไมต้องมี hyphen และมองว่าเวอร์ชันอื่นๆ ก็ไม่ได้มีความหมายมากนัก
หากไม่ได้จำเป็นต้องใช้ UUIDv7 หรือ UUID จริง ๆ https://github.com/segmentio/ksuid มี key space ที่ใหญ่กว่ามาก
ถ้าต้องการ namespace ก็เพียงเติม string prefix เข้าไป และความเป็นไปได้ที่จะเกิดการชนกันของ KSUIDก็น้อยกว่า UUID ทุกเวอร์ชันมาก
ในบรรดาตัวสร้าง ID แบบทั่วไปที่มี timestamp ซึ่งจัดเรียงได้ ksuid ดีที่สุด และมีไลบรารีสำหรับภาษาส่วนใหญ่
UUID v1~v7 สิ้นเปลืองเกินไป
ถ้ารับบิตที่เพิ่มขึ้นได้ ซึ่งส่วนใหญ่ก็น่าจะได้ KSUID เป็นรูปแบบที่ยอดเยี่ยม
[1] https://github.com/sophiabits/resource-id
แต่ปัญหาใหญ่ของ ksuid คือมันมี 160 บิต จึงไม่เข้ากับ native UUID type ของฐานข้อมูล เช่น PostgreSQL ทำให้มีต้นทุนด้านประสิทธิภาพ
1: https://github.com/svix/rust-ksuid
2: https://github.com/svix/python-ksuid
K-sortable เป็นแนวคิดที่ยอดเยี่ยม และคีย์ที่จัดเรียงได้แบบหลวม ๆ ช่วยแก้ use case ได้หลายแบบ
ชอบ representation แบบสตริงที่บีบอัดและมี type ด้วย
แต่ก็เป็นห่วงว่าผลข้างเคียงที่ไม่ได้ตั้งใจของ UUID v7 อาจทำให้เกิดปัญหาด้านความปลอดภัยมากขึ้น
คนเราไม่ควรใช้ UUID เป็น token และไม่ควรใช้เป็น primary key ของ DB แบบนั้นเช่นกัน แต่ในทางปฏิบัติก็ทำกัน
UUID v4 แท้จริงแล้วแทบจะเป็นเลขสุ่มเชิงเข้ารหัส ดังนั้นช่องโหว่ด้านความปลอดภัยจำนวนมากจนถึงตอนนี้จึงเหมือนรอดมาได้โดยบังเอิญ
เคยคิดว่าใน UUID v7 ข้อมูลสุ่มจริงถูกลดเหลือ 32 บิต และคิดว่าต้องให้ความรู้แก่นักพัฒนาให้ดีว่า UUID สามารถเดาได้
แก้ไข: ดูเหมือนว่าผมจะเข้าใจผิดเรื่องความสามารถในการคาดเดาของ UUID v7
ในร่างระบุว่าแนะนำให้ใช้ CSPRNG สำหรับบิตสุ่ม มีเอนโทรปีอย่างน้อย 74 บิต และออกแบบมาให้ “คาดเดาไม่ได้”
แม้จะบอกว่าในงานด้านความปลอดภัยให้ใช้ “UUID v4” แต่ก็น่าจะหมายถึงนัยที่เกี่ยวกับ timestamp
ถ้าชื่อเป็น UUIDv4 กับ UUIDv7 ดูเหมือนว่าจะเกิดความสับสนไม่รู้จบว่าตัวไหนเหมาะกับฐานข้อมูลและตัวไหนเหมาะกับ one-time token เพราะต้องคอยจำอยู่ตลอดหรือไม่
และก็นึกไม่ออกว่ามีวิธีแก้ที่ยังคง backward compatibility ได้ดีไหม
ใน Elixir เวลาสร้าง v4 UUID จะใช้ฟังก์ชัน
UUID.uuid4()ในทางทฤษฎีก็อาจสแกนโค้ดเพื่อดูการใช้งานได้ แต่เรื่องพวกนี้ล้วนเพิ่มโอกาสเกิดข้อผิดพลาด
แบบอิงแฮชอย่าง v3 ก็เช่นกัน
v4 นั้นเรียบง่ายและมีโอกาสถูกใช้ผิดน้อย