2008-10-10 62 views
11

Tóm tắt: Tôi đang phát triển ứng dụng web Java liên tục và tôi cần đảm bảo rằng tất cả tài nguyên tôi vẫn tồn tại có số nhận dạng duy nhất trên toàn cầu để ngăn trùng lặp.Tạo số nhận dạng duy nhất toàn cầu trong Java

Print Fine:

  1. tôi không sử dụng một RDBMS, vì vậy tôi không có bất kỳ máy phát điện tự ưa thích (ví dụ như một cung cấp bởi Oracle)
  2. Tôi muốn nó phải nhanh chóng, tốt nhất là tất cả trong bộ nhớ - tôi không muốn mở một tệp và tăng thêm một số giá trị
  3. Nó cần phải an toàn cho chủ đề (tôi dự đoán rằng chỉ một JVM tại một thời điểm sẽ cần phải tạo ID)
  4. Cần phải nhất quán ngay lập tức iations của JVM. Nếu máy chủ tắt và khởi động, trình tạo ID sẽ không tạo lại cùng một ID mà nó tạo ra trong các cảnh báo trước đó (hoặc ít nhất cơ hội phải thực sự, rất mỏng - tôi dự đoán có hàng triệu tài nguyên được phân bổ)
  5. Tôi đã xem các ví dụ trong bài viết mẫu ID duy nhất EJB. Chúng sẽ không làm việc cho tôi (tôi không muốn chỉ dựa vào System.currentTimeMillis() vì chúng tôi sẽ duy trì nhiều tài nguyên trên mỗi mili giây).
  6. Tôi đã xem câu trả lời được đề xuất trong this question. Mối quan tâm của tôi về họ là, cơ hội mà tôi sẽ nhận được một ID trùng lặp theo thời gian là gì? Tôi bị hấp dẫn bởi đề xuất sử dụng java.util.UUID cho một số UUID, nhưng một lần nữa, cơ hội trùng lặp cần phải nhỏ gọn.
  7. Tôi đang sử dụng JDK6
+0

bạn đang chạy nhiều trường hợp của các ứng dụng trên các máy khác nhau? Nếu bạn đang có, bạn có khả năng để bắt đầu máy lên theo lô - để nó có khả năng là nhiều quá trình sẽ bắt đầu trong cùng một mili giây? Nếu kẻ tấn công tìm cách gây ra vụ va chạm UUID, điều đó có ảnh hưởng đến tính bảo mật của ứng dụng của bạn không? –

+0

(A) Tập ID nào sẽ được tạo? Nhanh như thế nào? (Bao nhiêu/giây/phút) (B) Có, UUID được phát minh chính xác cho mục đích của bạn. –

Trả lời

30

Khá chắc chắn UUID là "đủ tốt". Có 340,282,366,920,938,463,463,374,607,431,770.000.000 UUID có sẵn.

http://www.wilybeagle.com/guid_store/guid_explain.htm

"Để đưa những con số này vào quan điểm, rủi ro hàng năm của một người bị trúng một thiên thạch được ước tính là một cơ hội trong 17 tỷ, có nghĩa là xác suất được khoảng ,00000000006 (6 × 10-11) , tương đương với tỷ lệ tạo ra hàng chục nghìn tỷ UUID trong một năm và có một bản sao. Nói cách khác, chỉ sau khi tạo ra 1 tỷ UUID mỗi giây trong 100 năm tới, xác suất tạo ra một bản sao sẽ là về 50%. Xác suất của một bản sao sẽ là khoảng 50% nếu mỗi người trên trái đất sở hữu 600 triệu UUID "

http://en.wikipedia.org/wiki/Universally_Unique_Identifier

+0

Tham khảo hay! Vì vậy, nó an toàn để suy ra rằng nếu tôi sử dụng UUID.randomUUID() trong ứng dụng của tôi, cơ hội của nó tạo ra cùng một UUID hai lần là vô cùng nhỏ sau đó ...? – Julie

+0

có, infinitesimally –

+1

Vâng, chỉ vì có rất nhiều giá trị có thể, không nhất thiết có nghĩa là họ đã viết các thuật toán đủ tốt để có được một phân phối ngẫu nhiên tốt. Sau đó, một lần nữa, các nhà thiết kế của lớp UUID có lẽ đã đặt nhiều suy nghĩ hơn vào nó hơn tôi có thể trong một buổi chiều! – Julie

1

Nếu nó cần phải là duy nhất trên mỗi PC: bạn có thể sử dụng (System.currentTimeMillis() << 4) | (staticCounter++ & 15) hoặc một cái gì đó tương tự.

Điều đó sẽ cho phép bạn tạo 16 mỗi ms. Nếu bạn cần nhiều hơn, hãy thay đổi bằng 5 và với 31 ...

nếu cần phải duy nhất trên nhiều máy tính, bạn cũng nên kết hợp trong địa chỉ MAC của thẻ mạng chính của bạn.

chỉnh sửa: để làm rõ

private static int staticCounter=0; 
private final int nBits=4; 
public long getUnique() { 
    return (currentTimeMillis() << nBits) | (staticCounter++ & 2^nBits-1); 
} 

và thay đổi nBits với căn bậc hai của số lượng lớn nhất bạn nên cần phải tạo ra cho mỗi ms.

Cuối cùng nó sẽ cuộn qua.Có lẽ 20 năm hoặc một cái gì đó với nBits tại 4.

+1

Đó là một cách thông minh để đi về nó. Tôi nghĩ tôi sẽ tin tưởng vào lớp UUID, vì @smiller đã cho tôi thêm tự tin rằng nó là "đủ độc đáo". – Julie

+0

Công ty của tôi sử dụng một hệ thống rất giống với điều này để tạo ra "UUID" của chúng tôi. Nó hoạt động ok (tôi chưa bao giờ thấy một bản sao). Nó có vẻ thực sự hacky mặc dù, và nó cũng cho phép bạn tìm ra nơi và khi một cái gì đó đã được tạo ra. – rmeador

+0

Đó là hacky trong đó tôi đã giới hạn bản thân mình trong một thời gian dài. Nếu bạn chỉ đơn giản là sử dụng hai thời gian dài và nối thêm một số vào currentTime trong một phương pháp đồng bộ, nó sẽ không thất bại trừ khi đồng hồ của bạn thay đổi. Nếu bạn lo lắng về điều đó, nó sẽ là tầm thường để sửa chữa quá. –

0

Từ bộ nhớ các gói từ xa RMI chứa trình tạo UUID. Tôi không biết liệu đó có đáng để xem xét không.

Khi tôi đã tạo chúng, tôi thường sử dụng mã băm MD5 của ngày giờ hiện tại, tên người dùng và địa chỉ IP của máy tính. Về cơ bản ý tưởng là để có tất cả mọi thứ mà bạn có thể tìm hiểu về máy tính/người và sau đó tạo ra một băm MD5 của thông tin này.

Nó hoạt động thực sự tốt và cực kỳ nhanh (khi bạn đã khởi tạo MessageDigest lần đầu tiên).

1
public class UniqueID { 
    private static long startTime = System.currentTimeMillis(); 
    private static long id; 

    public static synchronized String getUniqueID() { 
     return "id." + startTime + "." + id++; 
    } 
} 
+1

Giải pháp tốt và đơn giản, vâng.Mã bit UUID có lẽ sẽ được gọi nhiều nhất trong ứng dụng của tôi, bởi nhiều luồng cùng một lúc, do đó, quá trình đồng bộ hóa/nút cổ chai có thể quá nhiều. – Julie

+3

Không cuộn mã UUID của riêng bạn. Có rất nhiều cách tinh tế để làm cho nó sai. Mã này sẽ làm những điều xấu nếu nhiều quá trình bắt đầu trong cùng một mili giây, chẳng hạn như khi bạn bắt đầu một loạt các máy chạy cùng một tác vụ cùng một lúc. –

0

tại sao không làm như thế này

String id = Long.toString(System.currentTimeMillis()) + 
    (new Random()).nextInt(1000) + 
    (new Random()).nextInt(1000); 
+2

Tại sao bạn tạo 2 đối tượng ngẫu nhiên mới? –

0

nếu bạn muốn sử dụng một thực hiện ngắn hơn và nhanh hơn java UUID hãy xem tại địa chỉ:

https://code.google.com/p/spf4j/source/browse/trunk/spf4j-core/src/main/java/org/spf4j/concurrent/UIDGenerator.java

thấy những lựa chọn thực hiện và hạn chế trong javadoc.

đây là một thử nghiệm đơn vị về cách sử dụng:

https://code.google.com/p/spf4j/source/browse/trunk/spf4j-core/src/test/java/org/spf4j/concurrent/UIDGeneratorTest.java

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