2010-06-14 15 views
17

Tôi có cơ sở dữ liệu trong đó có 2 (hoặc có thể 3 hoặc 4) ứng dụng khác nhau đang chèn thông tin. Thông tin mới có ID của loại GUID/UUID, nhưng mỗi ứng dụng đang sử dụng một thuật toán khác để tạo ID. Ví dụ, người ta đang sử dụng "guid.comb" của NHibernate, người khác đang sử dụng NEWID của SQLServer(), người khác có thể muốn sử dụng thực thi Guid.NewGuid() của .NET.Nguy cơ va chạm UUID sử dụng các thuật toán khác nhau

Có nguy cơ xảy ra xung đột hoặc trùng lặp ID nào bình thường không?

Cảm ơn!

Trả lời

22

Nguy cơ va chạm được nâng lên một chút nhưng vẫn biến mất nhỏ. Hãy xem xét rằng:

  • Cả Comb và NEWID/NEWSEQUENTIALID bao gồm một dấu thời gian với độ chính xác xuống một vài ms . Do đó, trừ khi bạn đang tạo số lượng lớn ID tại cùng thời điểm chính xác từ tất cả các nguồn khác nhau này, theo nghĩa đen là không thể để ID bị va chạm.

  • Phần GUID mà không phải là dựa trên dấu thời gian có thể được coi là ngẫu nhiên; hầu hết các thuật toán GUID đều dựa trên các chữ số này trên một PRNG. Do đó, khả năng xảy ra xung đột giữa 10 byte còn lại này là theo thứ tự giống như khi bạn sử dụng hai trình tạo số ngẫu nhiên riêng biệt và theo dõi các xung đột. Hãy suy nghĩ về điều này trong một khoảnh khắc - PRNG có thể và làm các số lặp lại, do đó khả năng va chạm giữa hai trong số chúng không cao hơn đáng kể so với một va chạm chỉ sử dụng một trong số chúng, ngay cả khi chúng sử dụng các thuật toán hơi khác nhau. Nó giống như chơi các con số xổ số giống nhau mỗi tuần so với việc chọn một tập hợp ngẫu nhiên mỗi tuần - tỷ lệ cược thắng cũng giống hệt nhau.

Bây giờ, hãy nhớ rằng khi bạn sử dụng một thuật toán như Guid.Comb, bạn chỉ có 10 bit bộ duy nhất, tương đương với 1024 giá trị riêng biệt. Vì vậy, nếu bạn đang tạo ra một số lượng lớn GUID trong cùng một vài phần nghìn giây, bạn sẽ bị xung đột. Nhưng nếu bạn tạo GUID ở tần số khá thấp, nó không thực sự quan trọng có bao nhiêu thuật toán khác nhau bạn sử dụng cùng một lúc, khả năng xảy ra xung đột vẫn chưa thực sự tồn tại.

Cách tốt nhất để bạn hoàn toàn chắc chắn là chạy thử nghiệm; có tất cả 2 hoặc 3 (hoặc tuy nhiên nhiều bạn sử dụng) tạo GUIDs, cùng một lúc, đều đặn, và ghi chúng ra một tệp nhật ký, và xem bạn có bị va chạm (và nếu có, bao nhiêu). Điều đó sẽ cung cấp cho bạn một ý tưởng tốt về cách thức an toàn trong thực tế.

P.S.Nếu bạn đang sử dụng trình tạo lược của NHibernate để tạo GUID cho khóa chính được nhóm, hãy xem xét sử dụng NEWSEQUENTIALID() thay vì NEWID() - toàn bộ điểm Comb là tránh chia tách trang và bạn không hoàn thành được nếu bạn có các quy trình khác bằng cách sử dụng non- các thuật toán tuần tự. Bạn cũng nên thay đổi bất kỳ mã nào bằng cách sử dụng Guid.NewGuid để sử dụng cùng trình tạo Comb - thuật toán Lược thực tế được sử dụng trong NHibernate là not complicated và dễ sao chép trong logic miền của riêng bạn.

† Lưu ý rằng có vẻ như có tranh chấp về số NEWID và có chứa dấu thời gian hay không. Trong mọi trường hợp, vì nó được dựa trên địa chỉ MAC, phạm vi của các giá trị có thể nhỏ hơn đáng kể so với GUID V4 hoặc Comb. Lý do khác cho tôi để đề nghị gắn bó với Comb GUIDs bên ngoài cơ sở dữ liệu và NEWSEQUENTIALID bên trong cơ sở dữ liệu.

+0

Trong khi tôi (chủ yếu) đồng ý với kết luận của bạn, tôi phải chỉ ra một số lỗi. NEWID không bao gồm dấu thời gian; và dấu thời gian từ NEWSEQUENTIALID và Comb được lưu trữ trong các byte khác nhau, vì vậy bạn * có thể * nhận được các xung đột từ "GUID" được tạo ra tại các thời điểm khác nhau. Ngoài ra, dấu thời gian sử dụng của GUID (chẳng hạn như NEWSEQUENTIALID) làm * không * điền vào phần còn lại với số PRNG; họ sử dụng địa chỉ MAC. Đó là lý do tại sao tôi đề xuất chuẩn hóa trên một thuật toán tạo Guid đơn. –

+0

@Stephen: Tôi không thể chứng minh hoặc bác bỏ rằng 'NEWID' là dấu thời gian, vì tài liệu khan hiếm, nhưng AFAIK dựa trên thuật toán GUID của V1, sử dụng dấu thời gian. Và các byte dấu thời gian cho Comb và 'NEWSEQUENTIALID' phải là cùng một byte, nếu không chúng sẽ không thực sự được tuần tự. (Chúng sử dụng các kích cỡ khác nhau cho dấu thời gian, có, nhưng kích thước nhỏ hơn là 10 byte và do đó kết quả sẽ vẫn không bị va chạm với tần số chèn dưới 3,33 ms). – Aaronaught

+0

Dù sao, tôi đã thêm tuyên bố từ chối trách nhiệm; bất kể làm thế nào 'NEWID()' thực sự tạo ra ID của nó, tốt hơn là sử dụng 'NEWSEQUENTIALID' trên máy chủ nếu bạn dự định sử dụng Combs trên máy khách. – Aaronaught

3

Có, rủi ro ở trên mức bình thường, vì tất cả những điều này sử dụng các định nghĩa khác nhau của "GUID". Guid.NewGuid() là một GUID chủ yếu là ngẫu nhiên RFC, nhưng NEWSEQUENTIALID là một GUID được sắp xếp lại (và do đó không tuân thủ RFC) dựa trên địa chỉ MAC và dấu thời gian, và GUID của NHibernate hoàn toàn khác (dựa trên tính ngẫu nhiên và dấu thời gian).

Bạn có thể muốn xem xét việc chỉ chuẩn hóa trên một triển khai GUID. Tôi sử dụng loại GUID được chải kỹ cho tất cả các ứng dụng của mình. My blog có mô tả ngắn gọn về tất cả các loại GUID này cùng với các quyết định thiết kế cho riêng tôi.

Các vấn đề liên quan