Khi nào tôi nên sử dụng uuid.uuid1 () so với uuid.uuid4 () trong python?


207

Tôi hiểu sự khác biệt giữa hai từ các tài liệu.

uuid1():
Tạo UUID từ ID máy chủ, số thứ tự và thời gian hiện tại

uuid4():
Tạo UUID ngẫu nhiên.

Vì vậy, uuid1sử dụng thông tin máy / trình tự / thời gian để tạo UUID. Những ưu và nhược điểm của việc sử dụng mỗi là gì?

Tôi biết uuid1()có thể có những lo ngại về quyền riêng tư, vì nó dựa trên thông tin máy. Tôi tự hỏi liệu có còn tinh tế hơn khi chọn cái này hay cái kia không. Tôi chỉ sử dụng uuid4()ngay bây giờ, vì đó là một UUID hoàn toàn ngẫu nhiên. Nhưng tôi tự hỏi liệu tôi có nên sử dụng uuid1để giảm nguy cơ va chạm.

Về cơ bản, tôi đang tìm kiếm lời khuyên của mọi người về cách thực hành tốt nhất khi sử dụng cái này so với cái kia. Cảm ơn!


3
Đây là một cách tiếp cận khác với UUID. Mặc dù khả năng va chạm là vô hạn nhưng UUID không đảm bảo tính duy nhất. Để đảm bảo tính duy nhất, bạn có thể muốn sử dụng khóa ghép là [<id hệ thống>, <id cục bộ>]. Mỗi hệ thống tham gia chia sẻ dữ liệu phải có ID duy nhất của hệ thống hoặc được chỉ định trong quá trình thiết lập hệ thống hoặc thu được từ một nhóm ID chung. Id cục bộ là một ID duy nhất trong bất kỳ hệ thống cụ thể nào. Điều này liên quan đến nhiều rắc rối hơn nhưng đảm bảo tính độc đáo. Xin lỗi vì sự lạc quan, chỉ cố gắng giúp đỡ.
oᴉɹǝɥɔ

3
Không quan tâm đến "mối quan tâm riêng tư" mà anh ấy đã đề cập
Shrey

Câu trả lời:


253

uuid1()được đảm bảo không tạo ra bất kỳ va chạm nào (theo giả định bạn không tạo quá nhiều trong số chúng cùng một lúc). Tôi sẽ không sử dụng nó nếu điều quan trọng là không có kết nối giữa uuidmáy tính và máy tính, vì địa chỉ mac được sử dụng để làm cho nó trở nên độc nhất trên các máy tính.

Bạn có thể tạo các bản sao bằng cách tạo nhiều hơn 2 14 uuid1 trong chưa đầy 100ns, nhưng đây không phải là vấn đề đối với hầu hết các trường hợp sử dụng.

uuid4()như bạn đã nói, một UUID ngẫu nhiên. Cơ hội va chạm là rất, rất, rất nhỏ. Đủ nhỏ, bạn không nên lo lắng về nó. Vấn đề là, một trình tạo số ngẫu nhiên xấu làm cho nó có nhiều khả năng có va chạm.

Câu trả lời tuyệt vời này của Bob Aman tóm tắt nó một cách độc đáo. (Tôi khuyên bạn nên đọc toàn bộ câu trả lời.)

Thành thật mà nói, trong một không gian ứng dụng duy nhất không có các tác nhân độc hại, sự tuyệt chủng của tất cả sự sống trên trái đất sẽ xảy ra rất lâu trước khi bạn xảy ra va chạm, ngay cả trên UUID phiên bản 4, ngay cả khi bạn tạo ra khá nhiều UUID mỗi giây.


Xin lỗi, tôi đã nhận xét mà không nghiên cứu đầy đủ - có các bit dành riêng để giữ cho phiên bản 4 uuid không va chạm với phiên bản 1 uuid. Tôi sẽ xóa bình luận ban đầu của tôi. Xem công cụ.ietf.org/html/rfc4122
Đánh dấu tiền chuộc

1
@ss Vâng, có ý nghĩa với những gì tôi đã đọc. uuid1 là "độc đáo hơn", trong khi uuid4 là ẩn danh hơn. Vì vậy, về cơ bản sử dụng uuid1 trừ khi bạn có lý do để không. @mark tiền chuộc: Câu trả lời tuyệt vời, đã không xuất hiện khi tôi tìm kiếm uuid1 / uuid4. Có vẻ như thẳng từ miệng ngựa.
lửa

6
uuid1sẽ không nhất thiết tạo ra các UUID duy nhất nếu bạn tạo ra vài giây trên cùng một nút. Ví dụ : [uuid.uuid1() for i in range(2)]. Tất nhiên trừ khi có điều gì đó kỳ lạ đang xảy ra mà tôi đang thiếu.
Michael Mior 16/11/13

1
@Michael: uuid1có số thứ tự (phần tử thứ 4 trong ví dụ của bạn), vì vậy trừ khi bạn sử dụng hết tất cả các bit trong bộ đếm, bạn không có bất kỳ xung đột nào.
Georg Schölly

3
@Michael: Tôi đã thử nghiên cứu các trường hợp khi va chạm xảy ra và đã thêm thông tin tôi tìm thấy.
Georg Schölly

32

Một ví dụ khi bạn có thể xem xét uuid1()chứ không phải uuid4()khi UUIDs được sản xuất trên máy riêng biệt , ví dụ như khi nhiều giao dịch trực tuyến là quá trình trên một số máy để mở rộng mục đích.

Trong tình huống như vậy, các rủi ro của việc va chạm do lựa chọn kém trong cách tạo các số giả ngẫu nhiên, chẳng hạn, và số lượng UUID cao hơn có khả năng tạo ra nhiều khả năng tạo ID trùng lặp.

Một mối quan tâm khác uuid1(), trong trường hợp đó là máy mà mỗi GUID được tạo ra ban đầu được ghi lại hoàn toàn (trong phần "nút" của UUID). Thông tin này và thời gian, có thể giúp nếu chỉ với gỡ lỗi.


20

Nhóm của tôi gặp rắc rối khi sử dụng UUID1 cho tập lệnh nâng cấp cơ sở dữ liệu nơi chúng tôi đã tạo ~ 120 nghìn UUID trong vòng vài phút. Sự va chạm UUID dẫn đến vi phạm ràng buộc khóa chính.

Chúng tôi đã nâng cấp 100 máy chủ nhưng trên các phiên bản Amazon EC2 của chúng tôi, chúng tôi đã gặp phải sự cố này một vài lần. Tôi nghi ngờ độ phân giải đồng hồ kém và chuyển sang UUID4 đã giải quyết nó cho chúng tôi.


5

Một điều cần lưu ý khi sử dụng uuid1, nếu bạn sử dụng cuộc gọi mặc định (không đưa ra clock_seqtham số), bạn có cơ hội gặp phải va chạm: bạn chỉ có 14 bit ngẫu nhiên (tạo 18 mục trong vòng 100ns cho bạn khoảng 1% khả năng xảy ra va chạm nghịch lý sinh nhật / tấn công). Vấn đề sẽ không bao giờ xảy ra trong hầu hết các trường hợp sử dụng, nhưng trên một máy ảo có độ phân giải đồng hồ kém, nó sẽ cắn bạn.


7
@Guilaume sẽ rất hữu ích khi xem một ví dụ về thực hành tốt bằng cách sử dụng clock_seq....
eric

@Guilaume Bạn đã tính cơ hội 1% này như thế nào? 14 bit ngẫu nhiên có nghĩa là sự va chạm sẽ được đảm bảo xảy ra nếu bạn tạo> = 2 ^ 14 id trên 100ns và điều này có nghĩa là 1% khả năng xảy ra va chạm là khi bạn tạo ra khoảng 163 id trên 100 ns
maks

1
@maks Như tôi đã nói, bạn nên nhìn vào nghịch lý sinh nhật .
Guillaume

3

Có lẽ một cái gì đó không được đề cập là của địa phương.

Địa chỉ MAC hoặc thứ tự dựa trên thời gian (UUID1) có thể đủ khả năng tăng hiệu suất cơ sở dữ liệu, vì việc sắp xếp các số gần nhau hơn so với phân phối ngẫu nhiên (UUID4) (xem tại đây ).

Một vấn đề liên quan thứ hai, đó là việc sử dụng UUID1 có thể hữu ích trong việc gỡ lỗi, ngay cả khi dữ liệu gốc bị mất hoặc không được lưu trữ rõ ràng (điều này rõ ràng mâu thuẫn với vấn đề riêng tư được OP đề cập).


1

Ngoài câu trả lời được chấp nhận, có một tùy chọn thứ ba có thể hữu ích trong một số trường hợp:

v1 với MAC ngẫu nhiên ("v1mc")

Bạn có thể tạo kết hợp giữa v1 & v4 bằng cách cố tình tạo UUID v1 với địa chỉ MAC phát ngẫu nhiên (điều này được cho phép bởi thông số v1). UUID v1 kết quả phụ thuộc vào thời gian (như v1 thông thường), nhưng thiếu tất cả thông tin cụ thể của máy chủ (như v4). Nó cũng gần với v4 hơn trong khả năng chống va chạm: v1mc = 60 bit thời gian + 61 bit ngẫu nhiên = 121 bit duy nhất; v4 = 122 bit ngẫu nhiên.

Vị trí đầu tiên tôi gặp phải là hàm uuid_generate_v1mc () của Postgres . Kể từ khi tôi sử dụng python tương đương:

from os import urandom
from uuid import uuid1
_int_from_bytes = int.from_bytes  # py3 only

def uuid1mc():
    # NOTE: The constant here is required by the UUIDv1 spec...
    return uuid1(_int_from_bytes(urandom(6), "big") | 0x010000000000)

(lưu ý: Tôi đã có phiên bản dài hơn + nhanh hơn tạo trực tiếp đối tượng UUID; có thể đăng nếu có ai muốn)


Trong trường hợp khối lượng cuộc gọi LỚN / giây, điều này có khả năng làm cạn kiệt tính ngẫu nhiên của hệ thống. Bạn có thể sử dụng randommô-đun stdlib thay thế (nó có thể cũng sẽ nhanh hơn). Nhưng ĐƯỢC CẢNH BÁO: chỉ mất vài trăm UUID trước khi kẻ tấn công có thể xác định trạng thái RNG, và do đó dự đoán một phần UUID trong tương lai.

import random
from uuid import uuid1

def uuid1mc_insecure():
    return uuid1(random.getrandbits(48) | 0x010000000000)

Có vẻ như phương pháp này "giống như" v4 (thuyết bất khả tri), nhưng tệ hơn (ít bit hơn, phụ thuộc vào urandom, v.v.). Có bất kỳ lợi thế so với chỉ uuid4?
lửa

Đây chủ yếu chỉ là một bản nâng cấp cho các trường hợp v1 có ích cho chất lượng dựa trên thời gian của nó, nhưng khả năng chống va chạm mạnh hơn và quyền riêng tư của máy chủ là mong muốn. Một ví dụ là khóa chính cho cơ sở dữ liệu - so với v4, u uids v1 sẽ có vị trí tốt hơn khi ghi vào đĩa, có cách sắp xếp tự nhiên hữu ích hơn, v.v. Nhưng nếu bạn gặp trường hợp kẻ tấn công dự đoán 2 ** 61 bit là một vấn đề bảo mật (ví dụ như uuid a nonce), sau đó $ diety yes, sử dụng uuid4 thay thế (tôi biết tôi làm thế!). Re: tệ hơn vì nó sử dụng urandom, tôi không chắc ý của bạn là gì - dưới python, uuid4 () cũng sử dụng urandom.
Eli Collins

Thứ tốt, điều đó có ý nghĩa. Thật tốt khi thấy không chỉ những gì bạn có thể làm (mã của bạn), mà còn tại sao bạn muốn nó. Re: urandom, ý tôi là bạn đang tiêu thụ gấp đôi số ngẫu nhiên (1 cho uuid1, một cái khác cho urandom), vì vậy có thể sử dụng entropy hệ thống nhanh hơn.
lửa

Nó thực sự chỉ bằng một nửa so với uuid4: uuid1 () sử dụng 14 bit cho clock_seq, làm tròn tới 2 byte urandom. Trình bao bọc uuid1mc sử dụng 48 bit, nên ánh xạ tới 6 byte của urandom, với tổng số urandom (8) được tiêu thụ cho mỗi cuộc gọi. trong khi uuid4 trực tiếp gọi urandom (16) cho mỗi cuộc gọi.
Eli Collins
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.