Có nên cung cấp uuid

Đôi khi khách hàng có thể đã yêu cầu UUID tùy chỉnh, họ sẽ chỉ định một số UUID: kênh dữ liệu Bluetooth, kênh dữ liệu nối tiếp, cài đặt tham số mô-đun, v.v., UUID được sử dụng cho tham số tự xác định và kênh dữ liệu cụ thể.

UUID (Viết tắt của Universally Unique Identifier), còn được gọi là GUID (Globally Unique Identifier) là một giá trị duy nhất dài 128 bit. Một chuỗi UUID chuẩn sử dụng chữ số hex (octet):

0710a5ca-f57e-11e9-802a-5aa538984bd8


Có nên cung cấp uuid


Mục đích của UUID sinh ra là bởi vì:Dữ liệu lớn, kiểu khóa chính auto imcrement cần nhiều byte để lưu hơn. Và khóa chính kiểu này không phù hợp khi mà hệ thống có nhiều server, nhiều client cùng lúc truy cập trên toàn thế giới.

Bạn đang xem: Uuid là gì

Bạn đang xem: Uuid là gì

Bởi vậy UUID ra đời nhằm khắc phục những yếu điểm trên. Vậy nếu bạn đủ sức xây dựng một hệ thống với nhiều server, phục vụ hàng tỉ tỉ user hoặc chỉ đơn giản là không muốn để lộ id ra ngoài, hãy nghĩ tới UUID.

Trong bài này, chúng ta sẽ cùng tìm hiểu về UUID trong Java, thông qua class UUID.

2. Cấu trúc chuỗi UUID

Chúng ta cùng xem ví dụ về chuỗi UUID:

123e4567-e89b-42d3-a456-556642440000xxxxxxxx-xxxx-Bxxx-Axxx-xxxxxxxxxxxxA đại diện cho biến thể (variant) xác định bố cục (layout) của UUID. Tất cả các bit khác trong UUID phụ thuộc vào setting của các bit trong trường biến thể (variant field). Biến thể được xác định bởi 3 bit quan trọng nhất của A:

MSB1 MSB2 MSB3 0 X X reserved (0) 1 0 X current variant (2) 1 1 0 reserved for Microsoft (6) 1 1 1 reserved for future (7)Giá trị của A trong UUID là "a ". Tương đương nhị phân của "a" (=10xx) hiển thị biến thể là 2.B đại diện cho phiên bản (version). Phiên bản trong UUID (giá trị của B) là 4.

Java cung cấp các phương thức để lấy ra variant (biến thể) và version (phiên bản) của UUID như sau:

Java có cung cấp một implementation cho v3 và v4, nhưng cũng cung cấp một constructor để giúp người dùng tạo bất kỳ loại UUID nào:

UUID uuid = new UUID(long mostSigBits, long leastSigBits);

Version 3 & 5

Các UUID được tạo bằng cách sử dụng hàm băm của namespace và name. Các định danh namespace là các UUID giống như Domain Name System (DNS), Object Identifiers (OIDs), URLs,...

UUID = hash(NAMESPACE_IDENTIFIER + NAME)Sự khác biệt duy nhất giữa UUIDv3 và UUIDv5 là Thuật toán băm (Hashing Algorithm) - v3 sử dụng MD5 (128 bit) trong khi v5 sử dụng SHA-1 (160 bit).Nói một cách đơn giản, chúng ta cắt bớt kết quả băm thành 128 bit và sau đó thay thế 4 bit cho version (phiên bản) và 2 bit cho variant (biến thể).

Và đây là cách tạo UUID loại 3 trong java:

String source = namespace + name;byte bytes = source.getBytes("UTF-8");UUID uuid = UUID.nameUUIDFromBytes(bytes);Java không cung cấp implementation cho UUID loại 5.

Xem thêm: Back Order Là Gì - Giải Đáp Order Là Gì

Version 4

Implementation của UUID v4 trong Java sử dụng các số ngẫu nhiên. Class được java implement là SecureRandom. Nó sử dụng một giá trị không thể đoán trước để tạo ra các số ngẫu nhiên nhằm giảm tỷ lệ trùng.Để sinh chuỗi UUID v4, bạn sử dụng:

UUID uuid = UUID.randomUUID();Bạn có thể sinh unique key sử dụng ‘SHA-256" và UUID như sau:

MessageDigest salt = MessageDigest.getInstance("SHA-256");salt.update(UUID.randomUUID().toString().getBytes("UTF-8"));String digest = bytesToHex(salt.digest());

3. Kết luận

Vì cả hai hàm băm MD5 và SHA1 đều bị hỏng, nên tốt nhất khuyện bạn sử dụng v5. Nếu bạn chỉ cần tạo UUID đơn giản, loại 4 có thể đáp ứng tốt cho ứng dụng của bạn.

Bài viết này sẽ giới thiệu bạn về MySQL UUID, và hướng dẫn sử dụng nó như là primary key (PK), và trình bày về pros và cons trong việc sử dụng nó như primary key.

Giới thiệu MySQL UUID

Định danh duy nhất - Universally Unique IDentifier (UUID) được định nghĩa dựa trên RFC 4122, “a Universally Unique Identifier (UUID) URN Namespace).

UUDI là số duy nhất trên toàn cầu về mặt không gian và thời gian. 2 UUID là khác biệt nhau ngay cả khi được tạo ra từ 2 máy chủ riêng biệt.

Trong MySQL, UUID là 1 số dài 128-bit được biểu diễn dưới dạng chuỗi utf8 gồm 5 số thập lục phân theo định dạng sau:

aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee

Để tạo ra giá trị UUID, bạn sử dụng hàm UUID() như sau:

UUID()

Hàm UUID() trả về giá trị UUID tuân thủ theo UUID version 1 được mô tả trong RFC 4122.

Ví dụ:

mysql> SELECT UUID(); +--------------------------------------+ | uuid() | +--------------------------------------+ | 865234ad-6a92-11e7-8846-b05adad3f0ae | +--------------------------------------+ 1 row in set (0.05 sec)

MySQL UUID vs. Auto-Increment INT như primary key

Pros

Một số ưu điểm của UUID:

  • Vì là giá trị duy nhất trong tables, databases hay thậm chí là các servers khác nhau cho nên sẽ dễ dàng merge dữ liệu từ các databases khác nhau mà không sợ trùng id.
  • UUID không đi kèm với thông tin dữ liệu nên sẽ an toàn trên url. Ví dụ, nếu 1 user có id là 10 và truy cập theo link http://www.example.com/customers/10/, từ đó người dùng dễ đoán được các user khác bằng việc thay 10 thành 11, 12, … việc này dễ bị hacker tấn công.
  • UUID có thể được tạo ở mọi nơi tránh ảnh hưởng tới việc xoay vòng database server. Nó cũng đơn giản hóa logic trong ứng dụng. Ví dụ: để thêm dữ liệu vào bảng parent và bảng child, bạn phải thêm dữ liệu vào bảng parent trước, và tạo id và thêm dữ liệu vào bảng child. Bằng việc sử dụng UUID, bạn có thể tạo primary key của bảng parent trước và thêm dữ liệu vào cả 2 bảng parent và child trong cùng 1 transaction.

Cons

Một số nhược điểm của UUID:

  • UUID chiếm 16-bytes trong khi kiểu INT chiếm 4-bytes hoặc BIGINT chiếm8-bytes.
  • Có vẻ khó debug, tưởng tượng lệnh WHERE id = 'df3b7cb7-6a95-11e7-8846-b05adad3f0ae' với

    UUID() 0

  • Vì không được sắp xếp thứ tự và kích thước lớn dẫn đến hiệu năng thấp.

MySQL UUID solution

Trong MySQL, bạn có thể lưu UUID định dạng BINARY và hiển thị ra dạng VARCHAR bằng một số các hàm sau:

  • UUID() 1

  • UUID() 2

  • UUID() 3

Chú ý rằng các hàm

UUID() 4,

UUID() 5, và

UUID() 6 chỉ có trên MySQL >= 8.0.

Hàm

UUID() 4 chuyển UUID từ dạng VARCHAR sang dạng BINARY để lưu lại và sử dụng hàm

UUID() 5 để chuyển UUID từ dạng BINARY sang dạng VARCHAR để hiển thị ra.

Hàm

UUID() 6 trả về giá trị 1 nếu tham số đúng định dạng chuỗi UUID, ngược lại trả về 0. Trong trường hợp tham số là

mysql> SELECT UUID(); +--------------------------------------+ | uuid() | +--------------------------------------+ | 865234ad-6a92-11e7-8846-b05adad3f0ae | +--------------------------------------+ 1 row in set (0.05 sec) 0, hàm

UUID() 6 sẽ trả về

mysql> SELECT UUID(); +--------------------------------------+ | uuid() | +--------------------------------------+ | 865234ad-6a92-11e7-8846-b05adad3f0ae | +--------------------------------------+ 1 row in set (0.05 sec) 0.

Các UUID sau là hợp lệ trong MySQL:

aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee aaaaaaaabbbbccccddddeeeeeeeeeeee {aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee}

Ví dụ MySQL UUID

Ví dụ sau sử dụng UUID làm primary key.

Trước tiên tạo 1 bảng mới tên

mysql> SELECT UUID(); +--------------------------------------+ | uuid() | +--------------------------------------+ | 865234ad-6a92-11e7-8846-b05adad3f0ae | +--------------------------------------+ 1 row in set (0.05 sec) 3:

CREATE TABLE customers ( id BINARY(16) PRIMARY KEY, name VARCHAR(255) );

Thêm mới UUID vào cột

mysql> SELECT UUID(); +--------------------------------------+ | uuid() | +--------------------------------------+ | 865234ad-6a92-11e7-8846-b05adad3f0ae | +--------------------------------------+ 1 row in set (0.05 sec) 4:

INSERT INTO customers(id, name) VALUES(UUID_TO_BIN(UUID()),'John Doe'), (UUID_TO_BIN(UUID()),'Will Smith'), (UUID_TO_BIN(UUID()),'Mary Jane');

Khi truy xuất dữ liệu, sử dụng hàm

UUID() 5 để chuyển đổi dạng binary sang dạng human-readable:

SELECT BIN_TO_UUID(id) id, name FROM customers;

Có nên cung cấp uuid

Như vậy là ngoài cách tạo primary key bằng kiểu INT hay BIGINT, các bạn có thể sử dụng UUID để làm PRIMARY KEY tùy vào mục đích sử dụng dựa vào ưu điểm hay nhược điểm của nó.