2013-08-14 17 views
9

Potrzebuję wygenerować unikalny 10-cyfrowy identyfikator w Javie. Są to ograniczenia dla tego ID:Java: Unikatowy 10-cyfrowy identyfikator

  • Tylko numeryczne
  • maksymalnie 10 cyfr
  • Możliwość tworzenia do 10 różnych identyfikatorów na sekundę
  • musi być unikalne (nawet jeśli aplikacja wznawia)
  • Nie można zapisać numer w bazie danych
  • jak najszybciej, aby nie dodawać dużo lattency do systemu

Najlepszym rozwiązaniem znalazłem tak daleko jest następujące:

private static int inc = 0; 

private static long getId(){ 

    long id = Long.parseLong(String.valueOf(System.currentTimeMillis()) 
      .substring(1,10) 
      .concat(String.valueOf(inc))); 
    inc = (inc+1)%10; 
    return id; 
} 

To rozwiązanie ma następujące problemy:

  • Jeśli z jakiegoś powodu nie ma potrzeby tworzenia więcej niż 10 identyfikatorów za seccond , to rozwiązanie nie zadziała.
  • W około 32 lat identyfikator ten może się powtórzyć (Jest to prawdopodobnie dopuszczalne)

Inny sposób postępowania, aby utworzyć ten ID?

Jakieś inne problemy, o których nie myślałem z moimi?

Dzięki za pomoc,

+1

Czy kilka wystąpień aplikacji działa jednocześnie? – assylias

+0

Tylko jedna instancja działa teraz, ale może być możliwa w przyszłości. Mamy również drugą instancję na wypadek, gdyby podstawowy przestał działać, ale tylko jeden z nich (podstawowy lub drugi) działałby w tym samym czasie. – magodiez

+0

Jak wskazano w niektórych z poniższych odpowiedzi, moja implementacja zakończy się niepowodzeniem w środowisku z wieloma instancjami lub wieloma wątkami, więc zakładamy, że uruchomiona zostanie pojedyncza instancja z pojedynczym wątkiem. – magodiez

Odpowiedz

7

Jest to niewielka poprawa do Ciebie, ale powinny być odporny.

private static final long LIMIT = 10000000000L; 
private static long last = 0; 

public static long getID() { 
    // 10 digits. 
    long id = System.currentTimeMillis() % LIMIT; 
    if (id <= last) { 
    id = (last + 1) % LIMIT; 
    } 
    return last = id; 
} 

Jak to powinno być zarządzanie do 1000 na sekundę przy stosunkowo krótkim cyklu.Aby wydłużyć szybkość cyklu (ale skrócić rozdzielczość), możesz użyć (System.currentTimeMillis()/10) % 10000000000L lub (System.currentTimeMillis()/100) % 10000000000L.

+1

Jest to prawdopodobnie dobry pomysł, aby go również wątkować bezpieczne. – assylias

+0

Korzystanie z (System.currentTimeMillis()/100) faktycznie rozwiąże problem, jeśli w tym samym seccond musi być utworzonych więcej niż 10 ID, ponieważ nigdy nie będzie to coś ciągłego. Dzięki,;) – magodiez

+0

Pamiętaj, że 'System.currentTimeMillis()' ma minimalną rozdzielczość. Zauważyłem, że krążyło to około 15 ms w systemach MS, więc '/ 100' może nie być tak gładkie, jak ci się wydaje, chociaż ten algorytm zajmie się tym dla ciebie. – OldCurmudgeon

2

może to być szalony pomysł, ale jego pomysł :).

  • najpierw wygenerować UUID i uzyskać reprezentację ciąg niego z java.util.UUID.randomUUID().toString()
  • drugie konwersji generowanej ciąg do Byte Array (byte[])

  • następnie przekształcić go do długiej bufora: java.nio.ByteBuffer.wrap(byte digest[]).asLongBuffer().get()

  • Skróć do 10 cyfr

Nie jestem pewien co do wyjątkowości tego podejścia, wiem, że możesz polegać na unikalności UUID, ale nie sprawdzałeś, jak są one unikalne i czy są skracane do 10 cyfr.

Przykład został pobrany z JavaRanch, może jest coś więcej.

Edit: Jak są ograniczone do 10 cyfr może prosty losowy generator będzie dla ciebie za mało, zajrzyj do tego quesion/odpowiedzi na SO: Java: random long number in 0 <= x < n range

+0

[identyfikatory UUID są * nie * gwarantowane, że są unikatowe] (http://stackoverflow.com/questions/5728205/is-unique-id-generation-using-uuid-really-unique). Chociaż prawdopodobieństwo uzyskania dwóch identycznych UUID jest bardzo małe. – assylias

+1

Dokładnie, ale tak jak napisałem "możesz polegać na ich wyjątkowości", nie że są one unikalne :) – Kris

0

Co oznacza, że ​​musi być wyjątkowy? Nawet w bardziej obecnie działających instancjach? Łamie twoją implementację.

Jeśli musi być unikalny w całym wszechświecie, najlepszym rozwiązaniem jest użycie UUID, ponieważ jest to matematycznie sprawdzony generator identyfikatorów, ponieważ generuje unikalną wartość dla każdego wszechświata. Mniej dokładna liczba przynosi kolizje.

Jeśli występuje tylko jedna współbieżna instancja, można wziąć bieżący czas w milisekundach i rozwiązać problem o długości 10 ms, stosując przyrost. Jeśli poświęcisz odpowiednią liczbę ostatnich pozycji w liczbie, możesz uzyskać wiele numerów w ciągu jednej milisekundy. Chciałbym zdefiniować dokładność - mam na myśli to, ile unikatowych liczb potrzeba na sekundę. Rozwiążesz problem bez trwałości, korzystając z tego podejścia.

0

private static AtomicReference currentTime = new AtomicReference <> (System.currentTimeMillis());

public static Long nextId() { 
    return currentTime.accumulateAndGet(System.currentTimeMillis(), (prev, next) -> next > prev ? next : prev + 1) % 10000000000L; 
} 
+0

Proszę, edytuj odpowiedź, aby poprawnie sformatować kod. Dodaj również wyjaśnienie – Garf365

Powiązane problemy