2013-03-03 16 views
15

Ho un obbligo di generare identificatori lunghi univoci per la mia colonna di chiave primaria del database.Come generare un long UUID univoco

ho pensato che posso usare UUID.randomUUID(). GetMostSignificantBits() ma a volte la sua generazione di alcuni negativi a lungo anche che è problema per me.

È possibile generare solo positivo lungo da UUID? Ci saranno come miliardi di voci così voglio che ogni chiave generata deve essere unica.

+0

Perché non usi la sequenza? Sei in grado di usare cose del genere? O UUID questa è una soluzione che devi usare? –

+0

puoi spiegare di più sulla sequenza –

+0

Che DB usi? Quale framework db usi (JDBC, Hibernate, myBatis)? – Taky

risposta

4

Date un'occhiata a http://commons.apache.org/sandbox/commons-id//index.html Ha un generatore LongGener che può darvi esattamente ciò di cui avete bisogno.

Inoltre se si utilizza Hibernate allora si può chiedere per generare gli ID per voi (che ha diversi algoritmi si possono scegliere), in se non si può semplicemente dare un'occhiata al loro realizzazione, per esempio http://grepcode.com/file/repo1.maven.org/maven2/hibernate/hibernate/2.1.8/net/sf/hibernate/id/TableHiLoGenerator.java#TableHiLoGenerator)

+0

Beh, anche questo sembra buono. –

+0

LongGenerator creerà un ID sequenziale che significa che può scontrarsi. Mentre GUID è universalmente unico. Può bastare il requisito di Saurabh ma penso che questa non sia una risposta completamente corretta – Sap

+0

Apache commons-id non è disponibile per il download? Qualche altra alternativa? – user12458

1

Ho appena trovato questa soluzione. Per il momento sto cercando di capire la soluzione. Dice l'implementazione Java di twitter snowflake. Generatore di ID sequenziale a 64 bit basato sull'algoritmo di generazione di ID snowflake di Twitter.

https://github.com/Predictor/javasnowflake

Eventuali suggerimenti sono i benvenuti.

+0

Ma di nuovo vedo la stringa sincronizzata pubblica generateLongId(). Il blocco sincronizzato ridurrà le prestazioni a lungo termine, –

+1

In che modo long run o short run fanno la differenza in qualsiasi degrado delle prestazioni causato da una sincronizzazione? – user93353

+2

@SaurabhKumar Dubito fortemente che si verificheranno problemi di prestazioni con il piccolo blocco sincronizzato. Mentre la sincronizzazione è generalmente più lenta, non è sempre più lento di CAS (ad esempio, anche NIO di Java ha parlato molto bene) ed è decisamente più veloce di qualsiasi generatore di ID seriale del database (supponendo che abbiate bisogno dell'ID precedente, roundtrip del database ... ecc.). Dovresti sapere che ci sono anche una quantità enorme di altre cose che sono sincronizzate in Java (la maggior parte dei contenitori servlet lo fanno da qualche parte). –

3

Come gli altri hanno scritto, a lungo non ha spazio sufficiente per un numero univoco. Ma in molti casi un numero può essere abbastanza unico per un uso specifico. Ad esempio, un timestamp con precisione al nanosecondo è spesso sufficiente. Per farlo, spostare i millisecondi correnti 20 bits da allocare spazio per nanosecondi e quindi sovrapposizione con nanosecondi:

(System.currentTimeMillis() << 20) | (System.nanoTime() & ~9223372036854251520L); 

Il nano & ~ 9223372036854251520L parte prende nanosecondi corrente e imposta i primi 44 byte a 0, lasciando solo il giusto 20 bit che rappresentano nanosecondi fino a un millisecondo (999999 nano) è lo stesso:

nanoseconds & ~1111111111111111111111111111111111111111111100000000000000000000 

Lato nota: nanosecondi non devono essere utilizzate per rappresentare la corrente tempo perché il loro punto di partenza non è fisso nel tempo e perché vengono riciclati quando raggiungono il massimo.

È possibile utilizzare qualsiasi altra manipolazione di bit. Di solito è bene prendere in considerazione l'ora corrente e qualcos'altro come l'ID corrente del thread, id di processo, ip.

12
UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE 
+1

Mi piace perché non utilizza librerie di terze parti :) – DoctorD

Problemi correlati