Як завадити двом користувачам зареєструватися в один і той же момент з тим самим іменем користувача?


11

Ми не можемо серіалізувати реєстрації, оскільки мільйони користувачів реєструються одночасно. Паралельні реєстрації мають відбуватися.

Скажімо, база даних не містить імені користувача "user1". Коли двоє користувачів спробують зареєструватися в один і той же момент за допомогою "user1", він прийме його. Але це згодом спричинить проблеми. Це не повинно відбуватися.

Я шукаю логічне рішення. Нічого конкретного. Просто ідея вирішити це.


Давши пояснення у вашій попередній спробі опублікувати це на робочому місці, розгляньте питання про те, чому читати питання Чому питання інтерв'ю викликають бідні запитання Programmers.SE?
гнат

4
Це законна проблема архітектури програмного забезпечення. Не та проблема, яка викликає лише гарне запитання про інтерв'ю і більше нічого.
Карл Білефельдт

7
Мільйони користувачів, що реєструються одночасно? Дійсно? Якщо у вас одночасно реєструються мільйони користувачів, у вас є більші проблеми - наприклад, обробка мільярдів зареєстрованих користувачів. І, мабуть, гроші, щоб дозволити собі сервери, які цим обробляють
gnasher729

2
@AddzyK Це гіпотетична проблема, з якою ви стикаєтесь у майбутньому, з якою ви хочете отримати логічне рішення? Досить впевнений, що це поза сферою.
папараццо

3
Ось гіпотетична відповідь: заплатіть комусь іншому зробити це, що вже знає, що робити. З мільйонами нових користувачів / секунду ви отримаєте гроші.
whatsisname

Відповіді:


15

Скажімо, база даних не містить імені користувача "user1". Коли двоє користувачів спробують зареєструватися в один і той же момент за допомогою "user1", він прийме його.

Навіщо це прийняти? Просто застосувати унікальне обмеження, використовувати ім'я користувача як основний ключ або просто запустити реєстрацію коду програми всередині транзакції.

Ви повинні абсолютно мати можливість використовувати транзакції з базою даних, щоб не допустити цього. В іншому випадку жодна програма не зможе підтримувати інваріанти в даних бази даних.

Щодо масштабування, бази даних вже винайшли потрібні вам технології, як, наприклад, різні режими блокування залежно від того, яка саме послідовність вам потрібна, розподілені бази даних для декількох серверів баз даних тощо.


Чи блокування реєстрацій не заважає іншим користувачам одночасно реєструватися?
Addzy K

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. Асинхронний: зареєструйте користувача. Перечитайте запис користувача одразу після того, щоб переконатися, що він є незмінним та єдиним. Якщо це проблема, або попросіть користувача змінити (не настільки асинхронно), або надіслати йому повідомлення про те, що виникла проблема (асинхронна, але дратує з точки зору користувача), або дозвольте йому зареєструватися, але попросіть його надіслати електронну пошту (відключити) та змусити його змінити ім'я користувача в рамках процедури входу.

1

Перегляньте, що ви вважаєте унікальним ідентифікатором для користувача. У кожного користувача вже є унікальна адреса електронної пошти, тому ця проблема вже вирішена для вас. Звичайно, це означає, що кілька користувачів зможуть зареєструвати те саме ім’я, як "Майк Накіс". Чи є з цим проблема? Ти впевнений? Наприклад, це не проблема для facebook. Існує кілька користувачів фейсбуку під назвою "Майк Накіс". Подивіться на сторінку входу у facebook: вона запитує "електронну пошту чи телефон" та "пароль".


0

Оскільки мільйони користувачів реєструються одночасно, ви просто використовуєте сервери реєстрації 26 x 26, один для користувачів, починаючи з aa, один для користувачів, починаючи з ab і так далі. Як результат, на кожному сервері одночасно реєструються лише тисячі користувачів. Якщо ви все ще не можете впоратися з цим, використовуйте сервери 26 x 26 x 26.


5
... а потім власник вашого продукту хоче вийти на міжнародну ...
Теластин

2
Ті ж принципи застосовуються і до рядків Unicode, якщо вони знаходяться в нормалізованій формі, наприклад, NFKD. Ви також можете хешувати ім'я користувача та застосувати його на основі хеша. Однак ця відповідь - це лише реалізація власної розподіленої бази даних.
DeadMG

1
Ви маєте на увазі, що мільйони користувачів реєструються одночасно в одній країні ? У такому випадку у них повинно бути достатньо грошей, щоб заплатити більше за реальне рішення.
gnasher729

Більш конкретно, це лише початок роботи DHT.
DeadMG

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