Как предотвратить одновременную регистрацию двух пользователей с одинаковым именем пользователя?

11

Мы не можем сериализовать регистрации, поскольку одновременно регистрируются миллионы пользователей. Параллельные регистрации должны произойти.

Допустим, база данных не содержит имя пользователя 'user1'. Когда два пользователя пытаются зарегистрироваться одновременно с 'user1', он примет это. Но позже это вызовет проблемы. Этого не должно быть.

Я ищу логичное решение. Ничего конкретного. Просто идея, чтобы решить это.

Аддзи К
источник
Принимая во внимание вашу предыдущую попытку опубликовать это на Рабочем месте, подумайте над тем, чтобы прочитать « Почему вопросы на собеседовании вызывают проблемы у программистов. SE»?
комнат
4
Это законная проблема архитектуры программного обеспечения. Не та проблема, которая делает только хороший вопрос для интервью и больше ничего.
Карл Билефельдт
7
Миллионы пользователей регистрируются одновременно? В самом деле? Если одновременно регистрируются миллионы пользователей, у вас возникают более серьезные проблемы, например, обработка миллиардов зарегистрированных пользователей. И, вероятно, деньги, чтобы позволить себе серверы, которые справляются с этим.
gnasher729
2
@AddzyK Это гипотетическая проблема в будущем, которую вы хотите решить логически? Уверен, что это выходит за рамки здесь.
Папараццо
3
Вот гипотетический ответ: заплатите кому-то другому, чтобы он сделал это, кто уже знает, что делать. С миллионами новых пользователей в секунду вы получите деньги.
whatsisname

Ответы:

15

Допустим, база данных не содержит имя пользователя 'user1'. Когда два пользователя пытаются зарегистрироваться одновременно с 'user1', он примет это.

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

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

С точки зрения масштабирования, базы данных уже изобрели необходимые вам технологии, такие как различные режимы блокировки в зависимости от того, какая именно согласованность вам нужна, распределенные базы данных для нескольких серверов баз данных и т. Д.

DeadMG
источник
Не мешает ли блокировка регистрации другим пользователям регистрироваться одновременно?
Аддзи К
2
+1, только что выполнил грубую математику, и даже Facebook в среднем только несколько регистраций в секунду. Поэтому достаточно полагаться на собственные ограничения базы данных.
GrandmasterB
2
@AddzyK: Блокировка происходит только в течение короткого момента, когда база данных должна применять ограничения. Да, другие пользователи, регистрирующиеся одновременно, должны ждать в очереди, но это ожидание очень короткое и редко происходит в любом случае, даже в самых крупных системах.
Роберт Харви
1
@GrandmasterB Средние значения не могут рассказать полную историю здесь. Исходя из вопроса, я предположил, что это для обработки большой пиковой нагрузки, например, для переписи населения Австралии.
DeadMG
@AddzyK Это может сделать. По сути, вы можете обойтись только с блокировкой части стола. Существует множество схем для решения этой проблемы, например, ответ gnasher729, но я считаю, что вы сможете получить готовый продукт для распределенной базы данных, который сможет справиться с этим для вас. Даже если вам нужно развернуть собственную схему частичной блокировки, существует множество известных способов справиться с ней, например DHT.
DeadMG
7

Существует стандартное решение для этого. Создайте несколько рабочих для регистрации. К каждому запросу к имени пользователя применяется хеш, и хэш определяет, какой работник обрабатывает запрос. Таким образом, невозможно одновременно обрабатывать два запроса на одно и то же имя пользователя.

Для такого объема запросов рассмотрим хранилище значений распределенного ключа, такого как риск, вместо всей базы данных в качестве хранилища данных.

Майкл Шоу
источник
2

Это проблема ?

Разрешение двум пользователям завершить регистрацию с неуникальным именем пользователя недопустимо, если для входа в систему используется имя пользователя (а не адрес электронной почты пользователя).

Если имя пользователя не используется для аутентификации, вы можете использовать некоторый фоновый процесс для идентификации и пометки двойников (например, на основе метки времени) и заставить пользователя изменить свое имя пользователя при следующем входе в систему.

Да это проблема

Как вы спрашиваете, я предполагаю, что имя пользователя должно быть уникальным идентификатором. Можно использовать следующие подходы:

  1. До: в процессе регистрации предусмотрите шаг, при котором новый пользователь должен проверить наличие своего имени. При этом сохраните доступное имя учетной записи с временным статусом и идентификатором сеанса, который позволит завершить регистрацию.
  2. В то же время: более общий и гибкий вариант ответа gnasher729 заключался бы в использовании простой хеш-функции (аналогичной той, которая используется для управления таблицами символов) для назначения идентификатора уникальному серверу регистрации i (i = h (имя пользователя) по модулю number_of_servers), который будет обрабатывать уникальность в своей ограниченной / сегментированной области
  3. После: в конце регистрации, когда пользователь нажимает на кнопку registerотправить запрос в вашу транзакционную базу данных, если вы можете определить это поле как уникальное. В случае ошибки отправьте незадачливому пользователю сообщение «упс, возникла проблема» и попросите его выбрать другой идентификатор.
  4. Асинхронный: зарегистрировать пользователя. Перечитайте пользовательскую запись сразу после этого, чтобы убедиться, что она неизменна и единственная. Если это проблема, либо попросите пользователя изменить (не так асинхронно), либо отправьте ему письмо, в котором возникла проблема (асинхронное, но раздражающее с точки зрения пользователя), либо разрешите ему зарегистрироваться, но попросите его адрес электронной почты (для устранения неоднозначности) и заставить его изменить имя пользователя как часть процедуры входа в систему.
Christophe
источник
1

Пересмотрите то, что вы считаете уникальным идентификатором для пользователя. У каждого пользователя уже есть уникальный адрес электронной почты, поэтому эта проблема уже решена для вас. Конечно, это означает, что несколько пользователей смогут зарегистрировать одно и то же имя, например «Майк Накис». Есть ли проблема с этим? Вы уверены? Это не проблема для Facebook, например. Существует несколько пользователей Facebook под названием «Майк Накис». Посмотрите на страницу входа в Facebook: она запрашивает «адрес электронной почты или телефон» и «пароль».

Майк Накис
источник
0

Поскольку миллионы пользователей регистрируются одновременно, вы просто используете 26 х 26 серверов регистрации, один для пользователей, начинающихся с aa, один для пользователей, начинающихся с ab, и так далее. В результате на каждом сервере одновременно регистрируются только тысячи пользователей. Если вы все еще не можете справиться с этим, используйте серверы 26 x 26 x 26.

gnasher729
источник
5
... а затем ваш владелец продукта хочет выйти на международный
рынок
2
Те же принципы применяются к строкам Unicode, если они находятся в нормализованной форме, такой как NFKD. Вы также можете хэшировать имя пользователя и применять его на основе хэша. Тем не менее, этот ответ в основном просто реализует вашу собственную распределенную базу данных.
DeadMG
1
Вы имеете в виду, что в одной стране одновременно регистрируются миллионы пользователей ? В этом случае у них должно быть достаточно денег, чтобы платить больше за реальное решение.
gnasher729
В частности, это только начало того, как проводятся DHT.
DeadMG
Как это решает проблему, когда два пользователя регистрируют одно и то же имя одновременно - оба имени начинаются с одинаковых двух символов и поэтому обрабатываются одним и тем же сервером регистрации?
HorusKol