Створення зручних для читання / корисних, коротких, але унікальних ідентифікаторів


86
  • Потрібно обробляти> 1000, але <10000 нових записів на день

  • Не можна використовувати GUID / UUID, числа автоматичного збільшення тощо.

  • В ідеалі має бути 5 або 6 символів, звичайно, може бути альфа

  • Хотіли б повторно використовувати існуючі, добре відомі альгоси, якщо вони є

Щось там?


Чому б не використовувати INT або BIGINT, які автоматично збільшуються? Це, мабуть, найбільш читабельно і легко справляється з обсягом.
Малк

за Q вище, намагаючись зберегти його до 5/6 символів максимум і підтримуючи до 9999 нових записів на день
Кумар

@Kumar - Що робити, якщо за один день потрібно більше 9999 записів? Запропоноване вами рішення не здається стійким.
ChaosPandion 03.03.12

@ChaosPandion: Я думаю, це, мабуть, грубі здогади навантаження / трафіку, а не жорсткі межі. Я не впевнений, чому ви хочете встановити довільне обмеження кількості щоденних транзакцій.
Пол Сасік

Ви можете закодувати його в базу 64 і використовувати це. Я не впевнений, що ви можете зменшити його менше, ніж це, і все одно використовувати читабельні символи. Але я міг би стверджувати, що база 64 набагато менш читабельна, ніж база 32, оскільки для більшості символів (велике f, нижнє o, нижнє o проти просто f, oo) потрібно додати додатковий кваліфікатор.
Малк

Відповіді:


118

База 62 використовується tinyurl та bit.ly для скорочених URL-адрес. Це добре зрозумілий метод створення "унікальних", зручних для читання ідентифікаторів. Звичайно, вам доведеться зберігати створені ідентифікатори та перевіряти наявність дублікатів при створенні, щоб забезпечити унікальність. (Див. Код внизу відповіді)

Основа 62 метрики унікальності

5 символів в базі 62 дадуть вам 62 ^ 5 унікальних ідентифікаторів = 916 1332 832 (~ 1 мільярд) При 10 000 ідентифікаторів на день ви будете в порядку протягом 91 000 + днів

6 символів в базі 62 дадуть вам 62 ^ 6 унікальних ідентифікаторів = 56 800 235 584 (56+ мільярдів). При 10 000 ідентифікаторів на день ви будете в порядку протягом 5+ мільйонів днів

База 36 метрик унікальності

6 символів дадуть вам 36 ^ 6 унікальних ідентифікаторів = 2176782366 (2+ мільярди)

7 символів дадуть вам 36 ^ 7 унікальних ідентифікаторів = 78 364 164 096 (78+ мільярдів)

Код:

public void TestRandomIdGenerator()
{
    // create five IDs of six, base 62 characters
    for (int i=0; i<5; i++) Console.WriteLine(RandomIdGenerator.GetBase62(6));

    // create five IDs of eight base 36 characters
    for (int i=0; i<5; i++) Console.WriteLine(RandomIdGenerator.GetBase36(8));
}

public static class RandomIdGenerator 
{
    private static char[] _base62chars = 
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
        .ToCharArray();

    private static Random _random = new Random();

    public static string GetBase62(int length) 
    {
        var sb = new StringBuilder(length);

        for (int i=0; i<length; i++) 
            sb.Append(_base62chars[_random.Next(62)]);

        return sb.ToString();
    }       

    public static string GetBase36(int length) 
    {
        var sb = new StringBuilder(length);

        for (int i=0; i<length; i++) 
            sb.Append(_base62chars[_random.Next(36)]);

        return sb.ToString();
    }
}

Вихід:

z5KyMg
wd4SUp
uSzQtH
UPrGAT
UIf2IS

QCF9GNM5
0UV3TFSS
3MG91VKP
7NTRF10T
AJK3AJU7

3
виглядає фантастично, все, що не чутливе до регістру?
Кумар

2
Якщо ви хочете уникнути регістру, ви можете використовувати base 36: codeproject.com/Articles/10619/Base-36-type-for-NET-C, але щоб отримати стільки перестановок як base 62, вам потрібно буде використовувати більше символів у вашому Посвідчення особи. Це компроміс. Або ви можете спробувати використовувати інші символи, крім альфа-версії, але це стає негарним для користувачів.
Пол Сасік

2
тут stackoverflow.com/questions/9543892/… & велике спасибі
Кумар

11
Одна думка. Можливо, вийміть голосні, щоб запобігти випадковому породженню лайливих слів. Особливо, якщо це публічне обличчя.
Damien Sawyer

4
Залежно від того, де ви цим користуєтесь (особливо, якщо від людей очікується, що вони прочитають і повторно введуть коди), можливо, ви захочете видалити часто розгублені символи з розгляду: 0 / O та I / l / 1. Це може бути пом'якшено в деяких випадках гарним вибором шрифту, але я не можу сказати з питання, чи буде OP контролювати це.
GrandOpener

17

Я рекомендую http://hashids.org/, який перетворює будь-яке число (наприклад, DB ID) у рядок (за допомогою солі).

Це дозволяє декодувати цей рядок назад до числа. Тому вам не потрібно зберігати його в базі даних.

Має бібліотеки для JavaScript, Ruby, Python, Java, Scala, PHP, Perl, Swift, Clojure, Objective-C, C, C ++ 11, Go, Erlang, Lua, Elixir, ColdFusion, Groovy, Kotlin, Nim, VBA, CoffeeScript та для Node.js та .NET.


1
Чи можете ви надати інші варіанти, подібні до вашої пропозиції? - - Це дуже цікаво. Я хотів би знати, чи є такі параметри за замовчуванням, як у PostgreSQL.
Лео Леопольд Герц 준영

1
Ось його .NET- версія, але чи можете ви пояснити, як це працює, не зберігаючи її в базі даних? Чи можу я генерувати лише унікальні випадкові випадки, не вводячи цифри як вхідні дані та не вказуючи сіль?
shaijut

@Slawa Мені потрібно щось на зразок hashids для .NET, але остаточний хеш буде зберігатися в базі даних у стовпці з фіксованою довжиною, чи можна сказати, що завжди генерувати хеш з максимальною довжиною N?
Anon Dev

6

Я мав подібні вимоги, як OP. Я переглянув доступні бібліотеки, але більшість із них базуються на випадковості, і я цього не хотів. Я насправді не міг знайти нічого, що не базувалося б на випадковому і все ще було дуже коротким ... Тож я в підсумку прокатував свій власний заснований на техніці, яку використовує Flickr , але модифікований, щоб вимагати меншої координації та дозволяти триваліші періоди в автономному режимі.

Коротко:

  • Центральний сервер видає блоки ідентифікаторів, що складаються з 32 ідентифікаторів кожен
  • Локальний генератор ідентифікаторів підтримує пул блоків ідентифікаторів, щоб генерувати ідентифікатор кожного разу, коли його запитують. Коли пул закінчується, він отримує більше блоків ідентифікатора з сервера, щоб заповнити його знову.

Недоліки:

  • Потрібна центральна координація
  • Ідентифікатори більш-менш передбачувані (менше, ніж звичайні ідентифікатори DB, але вони не є випадковими)

Переваги

  • Залишається в межах 53 біт (максимальний розмір Javascript / PHP для цілих чисел)
  • дуже короткі посвідчення особи
  • База 36, закодована так легко для читання, написання та вимови
  • Ідентифікатори можна генерувати локально протягом дуже довгого часу, перш ніж знову потрібен контакт із сервером (залежно від налаштувань пулу)
  • Теоретично немає шансів на колізії

Я опублікував як бібліотеку Javascript для клієнта, так і реалізацію сервера Java EE. Впровадження серверів іншими мовами також повинно бути простим.

Ось проекти:

suid - короткі та солодкі унікальні ідентифікатори розподіленої послуги

suid-server-java - реалізація Suid-сервера для стеку технологій Java EE.

Обидві бібліотеки доступні за ліберальною ліцензією Creative Commons з відкритим кодом. Сподіваючись, це може допомогти комусь іншому, хто шукає короткі унікальні посвідчення особи.


Чи можете ви порівняти stackoverflow.com/a/29372036/54964 зі своєю пропозицією suid?
Лео Леопольд Герц,

1
Він базується на випадкових числах. Насправді це чудово. Але ваші посвідчення особи не повинні бути короткими, наскільки вони можуть бути. Я написав SUID, щоб почати нумерацію з 1, тому ви почнете з надзвичайно коротких посвідчень. Подумайте про 3 або 4 символи. Плюс, він має деякі інші приємні переваги мати (приблизно) поступово впорядковані посвідчення особи, окрім того, що починати з дійсно коротких.
Stijn de Witt

3

Я використовував базу 36, коли вирішував цю проблему для програми, яку розробляв пару років тому. Мені потрібно було створити зрозумілий для людини розумно унікальний номер (у будь-якому разі протягом поточного календарного року). Я вирішив використати час у мілісекундах з півночі 1 січня поточного року (щоб щороку мітки часу могли дублюватися) і перетворити його на базове число 36. Якщо система, що розробляється, зіткнулася зі смертельним результатом, вона генерує базове число 36 (7 символів), яке відображається кінцевому користувачеві через веб-інтерфейс, який потім може передати проблему (та номер) особі технічної підтримки (яка потім може використовувати його, щоб знайти точку в журналах, звідки починався стек). Таке число, як 56af42g7користувачеві нескінченно легше читати та передавати, ніж мітка часу, така як 2016-01-21T15: 34: 29.933-08: 00 або випадковий UUID, такий як 5f0d3e0c-da96-11e5-b5d2-0a1d41d68578 .


4
Чи можете ви надати псевдокод у структурованій формі щодо вашої пропозиції? Це звучить цікаво.
Лео Леопольд Герц 준영

0

Мені дуже подобається простота простого кодування GUID із використанням формату Base64 та скорочення кінцевого ==, щоб отримати рядок із 22 символів (це займає один рядок коду, і ви завжди можете перетворити його назад у GUID). На жаль, іноді він включає символи + та /. Добре для бази даних, не дуже для URL-адрес, але це допомогло мені оцінити інші відповіді :-)

З https://www.codeproject.com/Tips/1236704/Reducing-the-string-Length-of-a-Guid by Christiaan van Bergen

Ми виявили, що перетворення Guid (16 байт) у представлення ASCII за допомогою Base64 призвело до корисного та все ще унікального ідентифікатора повідомлення, що складається лише з 22 символів.

var newGuid = Guid.NewGuid();
var messageID = Convert.ToBase64String(newGuid.ToByteArray());

var message22chars = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Substring(0,22);

Наприклад: Посібник 'e6248889-2a12-405a-b06d-9695b82c0a9c' (довжина рядка: 36) отримає подання Base64: 'iYgk5hIqWkCwbZaVuCwKnA ==' (довжина рядка: 24)

Представлення Base64 закінчується символами '=='. Ви можете просто скоротити їх, не впливаючи на унікальність. Залишається вам ідентифікатор довжиною лише 22 символи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.