Последовательные GUID - PullRequest
       43

Последовательные GUID

11 голосов
/ 07 апреля 2011

Я надеюсь, что кто-то может ответить на этот вопрос.

Как метод UuidCreateSequential в классе rpcrt4.dll используется для заполнения его направляющих?

Я знаю это очень много: Microsoft изменила функцию UuidCreateпоэтому он больше не использует MAC-адрес аппарата как часть UUID.Поскольку CoCreateGuid вызывает UuidCreate для получения GUID, его выходные данные также изменились.Если вы все еще хотите, чтобы GUID генерировались в последовательном порядке (полезно для сохранения связанной группы GUID вместе в системном реестре), вы можете использовать функцию UuidCreateSequential.

Причина вопроса заключается в следующем.Если я использую эту функцию для генерации последовательных идентификаторов GUID в веб-кластере, как я могу гарантировать, что идентификаторы GUID близки к диапазону идентификаторов GUID без возможности дублирования идентификатора GUID?

Ответы [ 5 ]

30 голосов
/ 02 марта 2012

Win32 UuidCreateSequential создает Version 1 uuid .

Вот несколько примеров uuid версии 1, созданных на моем компьютере с использованием 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}

Первое, что важно отметить, что эти uuid содержат MAC-адрес моей машины (B8AC6FBE26E1):

enter image description here

                        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

Так что, если вы надеетесь, что разные компьютеры будут генерировать направляющие, которые «близки» друг к другу, вы будете разочарованы.

Давайте посмотрим на остальные значения.

Семь с половиной байтов из оставшихся 10 байтов являются меткой времени ;количество интервалов в 100 нс с 00: 00: 00 15 октября 1582 .Перестановка этих байтов меток времени вместе:

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

Вы можете видеть, что guid, созданные на одной машине с помощью UuidCreateSequential, будут вместе, поскольку они являются хронологическими.


The 1 вы видите номер версии , в данном случае означающий основанный на времени uuid.Существует 5 определенных версий:

  • 1: версия на основе времени (UuidCreateSequential)
  • 2: версия DCE Security со встроенными идентификаторами POSIX
  • 3: имяверсия на основе хэширования MD5
  • 4: случайно или псевдослучайно сгенерированная версия (UuidCreate)
  • 5: версия на основе имени, использующая хэширование SHA-1

Предоставление:

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

Последнее слово содержит две вещи.

Младшие 12 битов являются машинно-заданными Тактовая последовательность число:

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

Это постоянное значение для всей машины увеличивается, если:

  • вы переключили сетевые карты
  • вы сгенерировали UUID менее чем за 100 нс от последней (и метка времени столкнулась бы)

Итак, опять-таки, любой гид создан UuidCreateSequential будет (в идеале) иметь одинаковое число Clock Sequence , что делает их "близкими" друг к другу.

Последние 2 бита называются Variant ,и всегда установлен в двоичный файл 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

Так что у вас это есть.Последовательные руководства являются последовательными;и если вы создадите их на одном и том же компьютере , они будут "рядом" друг с другом в базе данных.


Но вы хотите знать, что на самом деле происходит с двумя последовательными UUID, созданнымина разных компьютерах.

Используя наши новые знания о руководствах версии 1, давайте сконструируем два guid для одной и той же временной метки с разных машин, например:

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

Сначала давайте вставим группу guid с последовательными временными метками.Сначала создайте временную таблицу для хранения нашего руководства, и cluster по guid:

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

CREATE clustered index IX_uuidorderingTest_uuid ON #uuidOrderingTest 
( 
   uuid
)

Теперь вставьте данные:

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}')

Примечание: я вставляю их в случайном порядке временных меток, чтобы проиллюстрировать, что SQL Server будет кластеризовать их.

Получить строки обратно и посмотреть, в каком порядке они расположены в последовательном (временная метка) порядке:

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

Теперь давайте вставим guid с:

  • теми же метками времени
  • , но с другим узлом (т. Е. MAC-адресом):

Вставьте новые направляющие с «другого» компьютера:

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}')

и получите результат:

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

Итак, у вас это есть.Порядок SQL Server Узел до Метка времени .Uuid, созданный на разных машинах, не будет сгруппирован вместе.Было бы лучше, если бы это не было сделано, но что ты будешь делать?

3 голосов
/ 07 апреля 2011

Вместо того, чтобы полагаться на Win32 API, я обычно использую свой собственный вариант последовательного гида, который заменяет восемь байтов стандартного гида тиками из даты и времени.

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 );
0 голосов
/ 23 марта 2017

Я изменил Томаса, ответьте, чтобы первые 8 байтов были инкрементными

 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);

, и результатом будет что-то вроде

b0c99468-714a-08d4-88bd-39e0b53455fb
b122b4b8-714a-08d4-9b12-924e850ad2fe
b1254cf0-714a-08d4-b7c9-954d36290ce5
b12573ff-714a-08d4-b000-632c3a58874d
0 голосов
/ 07 апреля 2011

У вас может быть центральная таблица, которая имеет последний известный начальный UID для диапазона и увеличивает его.

Например: DB1 создает GUID {AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766} и записывает это встол.DB2 подключается к сети и видит {AA333F14-FCCD-4bee-9F8F-9D9BDF1B8766} и увеличивает его на некоторое заданное число, например, 1 000 000 000 000 000 или что-то действительно высокое, поэтому у вас не будет перекрывающихся значений.

Но на самом деле GUIDпочти бесполезны при инкрементном использовании.

Я думаю, на самом деле вопрос в том, для чего вы используете GUID?Если вы хотите увеличить число, просто используйте 64-битный int (он же, bigint)

0 голосов
/ 07 апреля 2011

Не уверен насчет способа Win32, но вы можете использовать «недокументированный» newSequentialID () 'в MSSQL, если у вас есть подключение к базе данных MSSQL.

Я говорю «недокументированный», потому что он считается неверным при попытке сохранить его в качестве значения по умолчанию для столбца MSSQL Identity, и вы должны переопределить его и сказать, что хотите его использовать.

...