Ответ 1
Инженер из команды API Heroku: мы пошли с самым простым подходом к генерации имен приложений, что в основном вы предложили: сохранить массивы прилагательных и существительных в памяти, выбрать элемент из каждого наугад и объединить его с случайное число от 1000 до 9999.
Не самый захватывающий код, который я написал, но интересно посмотреть, что мы должны были сделать, чтобы масштабировать его:
-
Сначала мы выбирали имя, пытаясь
INSERT
, а затем спасая ошибку ограничения уникальности, чтобы выбрать другое имя. Это работало отлично, в то время как у нас был большой пул имен (и не очень большой набор приложений, использующих их), но в определенном масштабе мы начали замечать много столкновений во время генерации имени.Чтобы сделать его более устойчивым, мы решили выбрать несколько имен и проверить, какие из них по-прежнему доступны с одним запросом. Очевидно, что нам все еще нужно проверять ошибки и повторять попытки из-за условий гонки, но с таким количеством приложений в таблице это явно более эффективно.
У него также есть дополнительное преимущество, заключающееся в том, что мы можем получить предупреждение, если наш пул имен невелик (например: если выбрано 1/3 случайных имен, отправьте предупреждение).
-
В первый раз, когда у нас были проблемы с коллизиями, мы просто радикально увеличили размер нашего пула имен, перейдя от 2 цифр до 4. С 61 прилагательным и 74 существительными это заняло от ~ 400 тыс. до ~ 40 млн. имен (
61 * 74 * 8999
). -
Но к тому времени, когда мы запускали 2 миллиона приложений, мы снова начали получать предупреждения о столкновении и намного выше, чем ожидалось: около половины имен сталкивались с конфликтами, что не имело смысла, учитывая размер и сумму пула приложений.
Преступник, как вы могли догадаться, состоит в том, что
rand
является довольно плохим генератором псевдослучайных чисел. Выбор случайных элементов и чисел с помощьюSecureRandom
вместо этого радикально снизил количество столкновений, что соответствовало тому, что мы ожидали на первом месте.
С таким большим количеством работы, чтобы расширить этот подход, нам пришлось спросить, есть ли лучший способ сгенерировать имена на первом месте. Некоторые из обсуждаемых идей:
-
Сделать генерацию имен функцией идентификатора приложения. Это будет намного быстрее и полностью устранить проблему с коллизиями, но с другой стороны, это приведет к отмене большого количества имен с удаленными приложениями (и, черт возьми, у нас есть много приложений, созданных и удаленных вскоре после того, как в рамках различных интеграционных тестов).
-
Еще одна возможность сделать детерминирование генерации имен - иметь пул доступных имен в базе данных. Это упростит выполнение таких действий, как повторное использование имени через две недели после удаления приложения.
Взволнован, чтобы посмотреть, что мы будем делать в следующий раз, когда срабатывают предупреждения о столкновении!
Надеюсь, что это поможет любому, кто работает с дружественным названием.