c # - Sekventielle GUID'er

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg håber, at nogen kan svare på dette spørgsmål.


Hvordan bruger UuidCreateSequential-metoden i klassen rpcrt4.dll til at fræse det? S guider?


Jeg ved det meget:
Microsoft ændrede UuidCreate-funktionen, så den ikke længere bruger maskinens MAC-adresse som en del af UUID. Da CoCreateGuid kalder UuidCreate for at få sin GUID, ændres dens output også. Hvis du stadig kan lide GUID'erne, der skal genereres i rækkefølge for at holde en relateret gruppe GUID'er sammen i systemregistret), kan du bruge funktionen UuidCreateSequential.


Grunden til spørgsmålet er. Hvis jeg bruger denne funktion til at generere sekventielle GUID'er i en webklynge, hvordan kan jeg sikre, at GUID'erne er tæt på en række GUID'er uden at potentialet for GUID bliver dupliceret?

Bedste reference


Win32 UuidCreateSequential opretter en Version 1 uuid. [26]


Her er nogle prøveversioner 1 uuid'er oprettet på min computer ved hjælp af UuidCreateSequential:


{1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D85E-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D85F-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D860-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D861-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D862-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D863-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D864-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D865-63D1-11E1-80DB-B8AC6FBE26E1}
{220FB46C-63D1-11E1-80DB-B8AC6FBE26E1}


Den første ting, der er vigtigt at bemærke, at disse uuid indeholder min maskinens MAC-adresse (B8AC6FBE26E1):


Indtast billedbeskrivelse her


                        Node
======================= ============
1BE8D85D-63D1-11E1-80DB B8AC6FBE26E1
1BE8D85E-63D1-11E1-80DB B8AC6FBE26E1
1BE8D85F-63D1-11E1-80DB B8AC6FBE26E1
1BE8D860-63D1-11E1-80DB B8AC6FBE26E1
1BE8D861-63D1-11E1-80DB B8AC6FBE26E1
1BE8D862-63D1-11E1-80DB B8AC6FBE26E1
1BE8D863-63D1-11E1-80DB B8AC6FBE26E1
1BE8D864-63D1-11E1-80DB B8AC6FBE26E1
1BE8D865-63D1-11E1-80DB B8AC6FBE26E1
220FB46C-63D1-11E1-80DB B8AC6FBE26E1


Så hvis du 'håber på forskellige computere til at generere vejledninger, der er' tætte 'til hinanden, vil du blive skuffet.


Lad os se på resten af ​​værdierne.


Syv og en halv bytes af de resterende 10 byte er en tidsstempel ; Antallet af 100ns intervaller siden 00:00:00 15. oktober 1582 . Omlægning af disse tidsstempel bytes sammen:


Timestamp              Node
=============== ====== ============
1E163D11BE8D85D 1-80DB B8AC6FBE26E1
1E163D11BE8D85E 1-80DB B8AC6FBE26E1
1E163D11BE8D85F 1-80DB B8AC6FBE26E1
1E163D11BE8D860 1-80DB B8AC6FBE26E1
1E163D11BE8D861 1-80DB B8AC6FBE26E1
1E163D11BE8D862 1-80DB B8AC6FBE26E1
1E163D11BE8D863 1-80DB B8AC6FBE26E1
1E163D11BE8D864 1-80DB B8AC6FBE26E1
1E163D11BE8D865 1-80DB B8AC6FBE26E1
1E163D1220FB46C 1-80DB B8AC6FBE26E1


Du kan se, at vejledninger oprettet på samme maskine af UuidCreateSequential vil være sammen, da de er kronologiske.





1 du ser er versionsnummer , i dette tilfælde betyder en tidsbaseret uuid. Der er 5 definerede versioner:



  • 1: tidsbaseret version (UuidCreateSequential)

  • 2: DCE Sikkerhedsversion med indlejrede POSIX UID'er

  • 3: Navnbaseret version, der bruger MD5 hashing

  • 4: Randomly eller pseudo-tilfældigt genereret version (UuidCreate)

  • 5: Navnbaseret version, der bruger SHA-1 hashing



give:


Timestamp       Version      Node
=============== ======= ==== ============
1E163D11BE8D85D 1       80DB B8AC6FBE26E1
1E163D11BE8D85E 1       80DB B8AC6FBE26E1
1E163D11BE8D85F 1       80DB B8AC6FBE26E1
1E163D11BE8D860 1       80DB B8AC6FBE26E1
1E163D11BE8D861 1       80DB B8AC6FBE26E1
1E163D11BE8D862 1       80DB B8AC6FBE26E1
1E163D11BE8D863 1       80DB B8AC6FBE26E1
1E163D11BE8D864 1       80DB B8AC6FBE26E1
1E163D11BE8D865 1       80DB B8AC6FBE26E1
1E163D1220FB46C 1       80DB B8AC6FBE26E1


Det sidste ord indeholder to ting.


De nedre 12 bit er den maskinspecifikke Clock Sequence nummer:


Timestamp       Version   Clock Sequence   Node
=============== ======= = ================ ============
1E163D11BE8D85D 1       8 0DB              B8AC6FBE26E1
1E163D11BE8D85E 1       8 0DB              B8AC6FBE26E1
1E163D11BE8D85F 1       8 0DB              B8AC6FBE26E1
1E163D11BE8D860 1       8 0DB              B8AC6FBE26E1
1E163D11BE8D861 1       8 0DB              B8AC6FBE26E1
1E163D11BE8D862 1       8 0DB              B8AC6FBE26E1
1E163D11BE8D863 1       8 0DB              B8AC6FBE26E1
1E163D11BE8D864 1       8 0DB              B8AC6FBE26E1
1E163D11BE8D865 1       8 0DB              B8AC6FBE26E1
1E163D1220FB46C 1       8 0DB              B8AC6FBE26E1


Denne maskinvarige vedvarende værdi øges, hvis:



  • du skiftede netværkskort

  • du genererede en UUID mindre end 100 ns fra den sidste (og tidsstemplet ville kollidere)



Så vil alle guider, der er oprettet af UuidCreateSequential, igen have den samme Clock Sequence -nummer, hvilket gør dem 'nær' til hinanden.


De sidste 2 bit, kaldes en Variant , og er altid sat til binære 10:


Timestamp       Version Variant Clock Sequence   Node
=============== ======= ======= ================ ============
1E163D11BE8D85D 1       8       0DB              B8AC6FBE26E1
1E163D11BE8D85E 1       8       0DB              B8AC6FBE26E1
1E163D11BE8D85F 1       8       0DB              B8AC6FBE26E1
1E163D11BE8D860 1       8       0DB              B8AC6FBE26E1
1E163D11BE8D861 1       8       0DB              B8AC6FBE26E1
1E163D11BE8D862 1       8       0DB              B8AC6FBE26E1
1E163D11BE8D863 1       8       0DB              B8AC6FBE26E1
1E163D11BE8D864 1       8       0DB              B8AC6FBE26E1
1E163D11BE8D865 1       8       0DB              B8AC6FBE26E1
1E163D1220FB46C 1       8       0DB              B8AC6FBE26E1


Så der har du det. Sekventielle guider er sekventielle, og hvis du opretter dem på samme maskine , vil de være 'nær' til hinanden i en database.





Men du vil gerne vide, hvad der faktisk sker med to sekventielle UUID'er, der er oprettet på forskellige computere.


Brug vores nyfundne viden om Version 1 guider, lad os konstruere to guider for samme tidsstempel fra forskellige maskiner, f.eks .:


{1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1}
{1BE8D85D-63D1-11E1-80DB-123456789ABC}


Lad os først indsætte en masse guider med sekventielle tidsstempler. Opret først en midlertidig tabel for at gemme vores vejledninger i og klynge ved hjælp af guiden:


--DROP table #uuidOrderingTest
CREATE TABLE #uuidOrderingTest
( 
    uuid uniqueidentifier not null
)

CREATE clustered index IX\_uuidorderingTest\_uuid ON #uuidOrderingTest 
( 
   uuid
)


Indsæt nu dataene:


INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D866-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D862-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D861-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85E-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D864-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D863-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85F-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D865-63D1-11E1-80DB-B8AC6FBE26E1}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D860-63D1-11E1-80DB-B8AC6FBE26E1}')


Bemærk: Jeg indsætter dem i tilfældig tidsstempel rækkefølge for at illustrere, at SQL Server vil klynge dem.


Få rækkerne tilbage og se, hvilken rækkefølge de er i sekventiel (tidsstempel) rækkefølge:


SELECT * FROM #uuidOrderingTest

uuid
------------------------------------
1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D85E-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D85F-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D860-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D861-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D862-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D863-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D864-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D865-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D866-63D1-11E1-80DB-B8AC6FBE26E1


Nu kan vi indsætte guider med:



  • de samme tidsstempler

  • men forskellige node (dvs. MAC-adresse):



Indsæt de nye guider fra en 'anden' computer:


INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D866-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D862-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D861-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85E-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D864-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D863-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85F-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D85D-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D865-63D1-11E1-80DB-123456789ABC}')
INSERT INTO #uuidOrderingTest (uuid) VALUES ('{1BE8D860-63D1-11E1-80DB-123456789ABC}')


Og få resultaterne:


uuid
------------------------------------
1BE8D85D-63D1-11E1-80DB-123456789ABC
1BE8D85E-63D1-11E1-80DB-123456789ABC
1BE8D85F-63D1-11E1-80DB-123456789ABC
1BE8D860-63D1-11E1-80DB-123456789ABC
1BE8D861-63D1-11E1-80DB-123456789ABC
1BE8D862-63D1-11E1-80DB-123456789ABC
1BE8D863-63D1-11E1-80DB-123456789ABC
1BE8D864-63D1-11E1-80DB-123456789ABC
1BE8D865-63D1-11E1-80DB-123456789ABC
1BE8D866-63D1-11E1-80DB-123456789ABC
1BE8D85D-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D85E-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D85F-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D860-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D861-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D862-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D863-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D864-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D865-63D1-11E1-80DB-B8AC6FBE26E1
1BE8D866-63D1-11E1-80DB-B8AC6FBE26E1


Så der har du det. SQL Server-ordre Knude før Tidsstempel . Uuid oprettet fra forskellige maskiner vil ikke blive samlet sammen. Ville have været bedre, hvis det ikke havde gjort det, men whatcha vil gøre .

Andre referencer 1


I stedet for at stole på Win32 API, bruger jeg typisk min egen variant af en sekventiel guid, som erstatter otte byte af en standard guide med flåter fra en datetime.


var guidBinary = new byte[16];
Array.Copy( Guid.NewGuid().ToByteArray(), 0, guidBinary, 0, 8 );
Array.Copy( BitConverter.GetBytes( DateTime.Now.Ticks ), 0, guidBinary, 8, 8 );
return new Guid( guidBinary );

Andre referencer 2


Ikke sikker på Win32-vejen, men du kan bruge 'unocumented' 'newSequentialID ()' i MSSQL, hvis du har MSSQL-databaseforbindelse. [27]


Jeg siger 'undocumented' fordi den er behandlet som forkert, når du forsøger at gemme den som standardværdien for en MSSQL Identity-kolonne, og du skal tilsidesætte den og sige, at du vil bruge den.

Andre referencer 3


Du kunne have et centralt bord, der har den sidste kendte start UID for en rækkevidde og øge den.


fx: DB1 opretter en GUID {AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766} og skriver dette til bordet. DB2 kommer online og ser {AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766} og øger det med et bestemt antal, som 1.000.000.000.000.000 eller noget rigtigt højt, så du ikke vil have nogen overlappende værdier.


Men virkelig, GUID'er er næsten ubrugelige, når de anvendes trinvist.


Jeg gætter på det egentlige spørgsmål er, hvad bruger du GUID'er til? Hvis du vil have et incrmenting nummer, skal du bare bruge en 64bit int (aka, bigint)

Andre referencer 4


Jeg ændrede Thomas, svar på at have første 8 byte som inkrementale


 var guidBinary = new byte[16];
 Array.Copy(BitConverter.GetBytes(DateTime.Now.Ticks), 0, guidBinary, 0, 8);
 Array.Copy(Guid.NewGuid().ToByteArray(), 8, guidBinary, 8, 8);
 return new Guid(guidBinary);


og resultatet vil være noget lignende


b0c99468-714a-08d4-88bd-39e0b53455fb
b122b4b8-714a-08d4-9b12-924e850ad2fe
b1254cf0-714a-08d4-b7c9-954d36290ce5
b12573ff-714a-08d4-b000-632c3a58874d