Computer >> Máy Tính >  >> Lập trình >> Ruby

Tìm hiểu sâu về UUID và ULID

Một ngày nọ, nhóm HB đang trò chuyện và Ben, bậc thầy dev-ops của chúng tôi, đã đề cập rằng anh ấy ước mình sử dụng ULID thay vì UUID cho một hệ thống cụ thể.

Giống như bất kỳ kỹ sư dày dạn kinh nghiệm nào, phản ứng của tôi là lẩm bẩm một điều gì đó không cam kết rồi lẻn đến Google để tìm hiểu xem ULID là cái quái gì.

Hai giờ sau, tôi xuất hiện với cái nhìn chằm chằm dài hàng nghìn thước Anh và nhận ra rằng thế giới của những số nhận dạng duy nhất rộng lớn và kỳ diệu hơn những gì tôi có thể tưởng tượng.

Trước khi bắt đầu với ULID, hãy quay lại những điều cơ bản và thảo luận về UUID là gì:

Vấn đề với id "thông thường" là gì?

Hầu hết các ứng dụng web sử dụng cơ sở dữ liệu mặc định là id số tự động tăng lên. Ví dụ:trong Rails, bạn có thể thấy hành vi như thế này:

p1 = Person.create!
p1.id
# => 1

p2 = Person.create!
p2.id
# => 2

Cơ sở dữ liệu có thể tạo id tuần tự vì nó lưu trữ một bộ đếm tăng khi tạo bản ghi.

Mẫu này cũng có thể được nhìn thấy bên ngoài cơ sở dữ liệu. Đôi khi, chúng tôi cần gán id theo cách thủ công và chúng tôi có thể lưu trữ một bộ đếm tùy chỉnh trong - ví dụ - một phiên bản Redis.

Id tuần tự dễ triển khai đối với các trường hợp sử dụng khối lượng thấp, nhưng chúng trở nên khó khăn hơn khi khối lượng tăng lên:

  • Không thể tạo các bản ghi đồng thời vì mỗi phần chèn phải xếp hàng đợi để nhận được id của nó.
  • Việc yêu cầu id tuần tự có thể yêu cầu mạng vòng quanh và dẫn đến hiệu suất chậm hơn.
  • Rất khó để mở rộng quy mô kho dữ liệu cung cấp id tuần tự. Bạn phải lo lắng về việc các bộ đếm trên các máy chủ khác nhau không được đồng bộ hóa.
  • Nút có bộ đếm rất dễ trở thành một điểm lỗi duy nhất.

Id tuần tự cũng làm rò rỉ dữ liệu, có thể là sự cố trong một số trường hợp:

  • Bạn có thể dễ dàng đoán id tài nguyên có thể không thuộc về bạn.
  • Nếu bạn tạo một người dùng và id của người đó là 20, bạn biết rằng dịch vụ có 20 người dùng.

UUID ở quy mô web

UUID trông hơi khác so với id tuần tự. Chúng là các số 128 bit, thường được biểu thị bằng 32 chữ số thập lục phân:

123e4567-e89b-12d3-a456-426655440000

UUID được tạo bằng cách sử dụng các thuật toán cụ thể được xác định trong RFC 4122. Chúng cố gắng giải quyết nhiều vấn đề xảy ra với id tuần tự:

  • Bạn có thể tạo UUID trên bất kỳ số lượng nút nào mà không có bất kỳ trạng thái chia sẻ hoặc sự phối hợp nào giữa các nút.
  • Chúng khó đoán hơn một chút so với id tuần tự (sẽ nói thêm về điều đó ở phần sau)
  • Chúng không tiết lộ kích thước tập dữ liệu của bạn.

Điểm bắt buộc là có một cơ hội nhỏ là hai nút tạo ra cùng một id một cách độc lập. Sự kiện này được gọi là "va chạm".

Nhiều hương vị của UUID

Có năm loại thuật toán UUID được định nghĩa trong RFC 4122. Chúng được chia thành hai loại:

  • Dựa trên thời gian và ngẫu nhiên các thuật toán là những thứ chúng ta đã thảo luận. Chúng dẫn đến một UUID mới cho mỗi lần chạy.
    • Loại 4 :Một id được tạo ngẫu nhiên. Có lẽ là đặt cược tốt nhất của chúng tôi cho mã mới.
    • Loại 1 :ID chứa địa chỉ MAC của máy chủ và dấu thời gian hiện tại. Những thứ này không được dùng nữa vì chúng quá dễ đoán.
    • Loại 2 :Những điều này dường như không phổ biến. Chúng dường như được xây dựng có mục đích cho một dạng RPC cổ xưa.
  • Các thuật toán dựa trên tên có một chút khác biệt. Chúng luôn tạo ra cùng một UUID cho một tập hợp đầu vào nhất định.
    • Loại 5 :Sử dụng hàm băm SHA-1 để tạo UUID. Được đề xuất.
    • Loại 3 :Sử dụng băm MD5 và không được dùng nữa vì MD5 quá không an toàn.

Trong Ruby, bạn có thể tạo UUID thông qua uuidtools đá quý. Nó hỗ trợ mọi loại, ngoại trừ loại bí ẩn 2;

# Code stolen from the uuidtools readme. :)
require "uuidtools"

# Type 1
UUIDTools::UUID.timestamp_create
# => #<UUID:0x2adfdc UUID:64a5189c-25b3-11da-a97b-00c04fd430c8>

# Type 4
UUIDTools::UUID.random_create
# => #<UUID:0x19013a UUID:984265dc-4200-4f02-ae70-fe4f48964159>

# Type 3
UUIDTools::UUID.md5_create(UUIDTools::UUID_DNS_NAMESPACE, "www.widgets.com")
# => #<UUID:0x287576 UUID:3d813cbb-47fb-32ba-91df-831e1593ac29>

# Type 5
UUIDTools::UUID.sha1_create(UUIDTools::UUID_DNS_NAMESPACE, "www.widgets.com")
# => #<UUID:0x2a0116 UUID:21f7f8de-8051-5b89-8680-0195ef798b6a>

Chuyển sang ULID

Lưu ý: Trong phiên bản gốc của bài đăng blog này, tôi đã quên liên kết đến thông số ULID. Nó đây. Nó cung cấp các liên kết đến việc triển khai bằng Ruby và các ngôn ngữ khác.

ULID là một công cụ mới hữu ích với các số nhận dạng duy nhất. Sự khác biệt rõ ràng nhất là chúng trông hơi khác một chút:

01ARZ3NDEKTSV4RRFFQ69G5FAV

Chúng được tạo thành từ hai số được mã hóa base32; dấu thời gian UNIX theo sau là một số ngẫu nhiên. Đây là cấu trúc, như được định nghĩa trong đặc điểm kỹ thuật:

01AN4Z07BY      79KA1307SR9X4MV3

|----------|    |----------------|
 Timestamp          Randomness
   48bits             80bits

Cấu trúc này thật hấp dẫn! Nếu bạn nhớ lại, UUID dựa vào dấu thời gian hoặc tính ngẫu nhiên, nhưng ULID sử dụng cả dấu thời gian tính ngẫu nhiên.

Do đó, ULID có một số thuộc tính thú vị:

  • Chúng có thể sắp xếp theo từ vựng (tức là theo thứ tự bảng chữ cái).
  • Dấu thời gian chính xác đến từng mili giây
  • Chúng đẹp hơn UUIDs :)

Những điều này mở ra một số khả năng thú vị:

  • Nếu bạn đang phân vùng cơ sở dữ liệu của mình theo ngày, bạn có thể sử dụng dấu thời gian được nhúng trong ULID để chọn phân vùng chính xác.
  • Bạn có thể sắp xếp theo ULID thay vì cột tạo_at riêng biệt nếu chấp nhận được độ chính xác mili giây.

Cũng có một số nhược điểm có thể xảy ra:

  • Nếu để lộ dấu thời gian là một ý tưởng tồi cho ứng dụng của bạn, thì ULID có thể không phải là lựa chọn tốt nhất.
  • sort by ulid phương pháp tiếp cận có thể không hoạt động nếu bạn cần độ chính xác dưới mili giây.
  • Theo Internet, một số triển khai ULID không chống được đạn.

Kết luận

UUID đang và sẽ tiếp tục là tiêu chuẩn. Chúng đã tồn tại mãi mãi và các thư viện có sẵn bằng mọi ngôn ngữ có thể tưởng tượng được. Tuy nhiên, các phương pháp tiếp cận mới đáng được xem xét, đặc biệt là khi chúng ta bước vào một thế giới ngày càng được vận hành bởi các hệ thống phân tán. Các phương pháp tiếp cận id duy nhất mới có thể giúp chúng tôi giải quyết các vấn đề không phổ biến khi xuất bản RFC4122.