Создать уникальный идентификатор

Я учусь в университете и наша задача создать поисковую систему. У меня возникают трудности с созданием уникального идентификатора для назначения каждому URL-адресу при добавлении в границу. Я попытался использовать алгоритм хеширования SHA-256, а также Guid. Вот код, который я использовал для реализации руководства:

public string generateID(string url_add)
{
    long i = 1;

    foreach (byte b in Guid.NewGuid().ToByteArray())
    {
        i *= ((int)b + 1);
    }

    string number = String.Format("{0:d9}", (DateTime.Now.Ticks / 10) % 1000000000);

    return number;
}

person strange_developer    schedule 03.07.2012    source источник
comment
GUID должен быть глобально уникальным (отсюда и название), поэтому я не понимаю проблемы.   -  person CodeCaster    schedule 03.07.2012
comment
Я думаю, что его беспокоит то, что он хочет, чтобы идентификатор был уникальным на основе URL-адреса, поэтому односторонний хэш URL-адреса для уникального идентификатора. В этом случае SHA1 будет работать.   -  person Richthofen    schedule 03.07.2012
comment
Всегда есть object.GetHashCode(). Хотя я не думаю, что это гарантированно уникально.   -  person RichardTowers    schedule 03.07.2012
comment
@RichardTowers, который почти гарантированно не уникален   -  person CodesInChaos    schedule 03.07.2012
comment
простой ответ: return url_add;   -  person CodesInChaos    schedule 03.07.2012
comment
Как упоминалось в ответах, проверьте Guid.NewGuid()< /а>.   -  person Samuel Parkinson    schedule 03.07.2012


Ответы (7)


Почему бы просто не использовать ToString?

public string generateID()
{
    return Guid.NewGuid().ToString("N");
}

Если вы хотите, чтобы он основывался на URL-адресе, вы можете просто сделать следующее:

public string generateID(string sourceUrl)
{
    return string.Format("{0}_{1:N}", sourceUrl, Guid.NewGuid());
}

Если вы хотите скрыть URL-адрес, вы можете использовать некоторую форму SHA1 для исходного URL-адреса, но я не уверен, чего это может достичь.

person Jaime Torres    schedule 03.07.2012
comment
Это сработало... Сначала я хотел, чтобы идентификатор основывался на URL-адресе, но, похоже, это работает нормально. Сможет ли он генерировать большое количество уникальных ключей? Потому что поисковая система будет работать с большим количеством URL-адресов. - person strange_developer; 03.07.2012
comment
Таким образом можно получить приблизительно 5 316 911 983 139 663 491 615 228 241 121 400 000 уникальных значений. - person Jaime Torres; 03.07.2012
comment
Большое спасибо! Этого более чем достаточно, поскольку URL-адреса извлекаются из границы, а затем удаляются. - person strange_developer; 03.07.2012
comment
Спасибо! Основание на URL-адресе также сработало! Я полагаю, что использование URL-адреса сделает его более уникальным и уменьшит вероятность столкновения! Большое спасибо!!! - person strange_developer; 03.07.2012
comment
О нет! снова протестировал код на основе URL-адреса, и он не сработал... Но первый работает отлично! - person strange_developer; 03.07.2012
comment
Я ошибочно использовал его как string.format вместо string.Format... это было источником вашей проблемы? - person Jaime Torres; 03.07.2012
comment
Что касается создания идентификатора без использования идентификатора на основе URL-адреса, будут ли символы всегда иметь фиксированную длину? Запрос для целей структуры db - person strange_developer; 03.07.2012
comment
Да, рекомендуется определенная структура. Общая длина строки Guid.ToString(N) будет составлять 32 символа. - person Jaime Torres; 03.07.2012
comment
Для большей справедливости используйте String.Format("{0}_{1:N}", sourceUrl, Guid.NewGuid()) - person abatishchev; 15.02.2014

Почему бы не использовать GUID?

Guid guid = Guid.NewGuid();
string str = guid.ToString();
person abatishchev    schedule 03.07.2012

Вот генератор идентификаторов «YouTube-video-id», например. "UcBKmq2XE5a"

StringBuilder builder = new StringBuilder();
Enumerable
   .Range(65, 26)
    .Select(e => ((char)e).ToString())
    .Concat(Enumerable.Range(97, 26).Select(e => ((char)e).ToString()))
    .Concat(Enumerable.Range(0, 10).Select(e => e.ToString()))
    .OrderBy(e => Guid.NewGuid())
    .Take(11)
    .ToList().ForEach(e => builder.Append(e));
string id = builder.ToString();

Он создает случайные идентификаторы размером 11 символов. Вы также можете увеличить/уменьшить его, просто изменив параметр метода Take.

0,001% дубликатов на 100 миллионов.

person Ashraf Ali    schedule 07.07.2017
comment
Как вы думаете, можно ли использовать этот номер заказа для электронной коммерции? есть ли шанс, что два заказа получат один и тот же идентификатор, используя этот метод? учитывая, что, возможно, будет 1К или 10К заказов в день? - person Mahamad Husen; 05.05.2020
comment
Я бы не рекомендовал использовать описанный выше подход в вашем случае. Лучший вариант - использовать Guid. Также взгляните на этот github.com/ dotnet/aspnetcore/blob/master/src/Servers/Kestrel/ - person Ashraf Ali; 05.05.2020
comment
хорошо, в моем случае, если я перефразирую, мне нужно что-то точно такое же, как в вашем решении (буквенно-цифровая строка около 8 символов), чтобы использовать его в качестве OrderNo в приложении электронной коммерции, я только что добавил ваше решение в свой проект + проверка дубликатов по БД, если да, сгенерировать новый. подходит ли этот класс CorrelationIdGenerator для моего сценария? - person Mahamad Husen; 05.05.2020

Почему мы не можем создать уникальный идентификатор, как показано ниже.

Мы можем использовать DateTime.Now.Ticks и Guid.NewGuid().ToString() для объединения и создания уникального идентификатора.

По мере добавления DateTime.Now.Ticks мы можем узнать дату и время в секундах, когда создается уникальный идентификатор.

Пожалуйста, смотрите код.

var ticks = DateTime.Now.Ticks;
var guid = Guid.NewGuid().ToString();
var uniqueSessionId = ticks.ToString() +'-'+ guid; //guid created by combining ticks and guid

var datetime = new DateTime(ticks);//for checking purpose
var datetimenow = DateTime.Now;    //both these date times are different.

Мы даже можем взять часть тиков в уникальном идентификаторе и проверить дату и время позже для дальнейшего использования.

person Jineesh Uvantavida    schedule 30.05.2017

Если вы хотите использовать sha-256 (руководство будет быстрее), вам нужно будет сделать что-то вроде

SHA256 shaAlgorithm = new SHA256Managed();
byte[] shaDigest = shaAlgorithm.ComputeHash(ASCIIEncoding.ASCII.GetBytes(url));
return BitConverter.ToString(shaDigest);

Конечно, это не обязательно должен быть ascii, и это может быть любой другой алгоритм хеширования.

person daz-fuller    schedule 03.07.2012
comment
Я бы избегал ASCII в пользу некоторой кодировки Unicode. По вашему коду легко найти коллизии. - person CodesInChaos; 03.07.2012
comment
Я знаю, это потому, что в данный момент я работаю с устаревшей системой, поэтому я подключен к ascii :) - person daz-fuller; 03.07.2012
comment
Я хочу, чтобы идентификатор был уникальным на основе URL-адреса. Вот как я думал о создании кода - person strange_developer; 03.07.2012

Кажется, на этот вопрос дан ответ, однако для полноты картины я бы добавил еще один подход.

Вы можете использовать генератор уникальных идентификационных номеров, основанный на Snowflake генераторе идентификаторов Twitter. Реализацию C# можно найти здесь.

var id64Generator = new Id64Generator();

// ...

public string generateID(string sourceUrl)
{
    return string.Format("{0}_{1}", sourceUrl, id64Generator.GenerateId());
}

Обратите внимание, что одной из очень приятных особенностей этого подхода является возможность иметь несколько генераторов на независимых узлах (вероятно, что-то полезное для поисковой системы), генерирующих в реальном времени глобально уникальные идентификаторы.

// node 0
var id64Generator = new Id64Generator(0);

// node 1
var id64Generator = new Id64Generator(1);

// ... node 10
var id64Generator = new Id64Generator(10);
person Tom    schedule 18.07.2015
comment
Спасибо за совет! Именно то, что я искал. - person Sudhanshu Mishra; 15.05.2016
comment
На github.com/RobThree/IdGen есть код NuGet, который также выполняет аналогичные идентификаторы на основе снежинок. Принадлежит ли вам код codeplex для FlakeId? Я хотел бы получить его на github и сделать nuget, если это нормально? - person Sudhanshu Mishra; 15.05.2016
comment
@dotnetguy, да, он у меня есть. Конечно, вы можете воспользоваться миграцией github и пакетом nuget. - person Tom; 16.05.2016

Мы можем сделать что-то вроде этого

string TransactionID = "BTRF"+DateTime.Now.Ticks.ToString().Substring(0, 10);
person Mohsin Khan    schedule 02.12.2019