Jak zapobiec rejestracji dwóch użytkowników w tym samym momencie przy użyciu tej samej nazwy użytkownika?

11

Nie możemy serializować rejestracji, ponieważ miliony użytkowników rejestrują się jednocześnie. Konieczne są równoległe rejestracje.

Załóżmy, że baza danych nie zawiera nazwy użytkownika „użytkownik1”. Gdy dwóch użytkowników spróbuje zarejestrować się w tym samym momencie jako „użytkownik1”, zaakceptuje to. Ale później spowoduje problemy. To nie powinno się zdarzyć.

Szukam logicznego rozwiązania. Nic konkretnego. Pomysł, aby to rozwiązać.

Addzy K
źródło
wyjaśnione w poprzedniej próbie opublikowania tego w Miejscu Pracy, zastanów się nad przeczytaniem Dlaczego pytania podczas wywiadu sprawiają, że pytania w Programmers.SE są kiepskie?
komar
4
Jest to uzasadniony problem architektury oprogramowania. Nie jest to problem, który stanowi tylko dobre pytanie do rozmowy kwalifikacyjnej i nic więcej.
Karl Bielefeldt,
7
Miliony użytkowników rejestrujących się jednocześnie? Naprawdę? Jeśli miliony użytkowników rejestrują się w tym samym czasie, masz większe problemy - na przykład obsługę miliardów zarejestrowanych użytkowników. I prawdopodobnie pieniądze na serwery, które sobie z tym poradzą.
gnasher729,
2
@AddzyK To jest hipotetyczny problem, który napotyka w przyszłości, dla którego chcesz logiczne rozwiązanie? Jestem całkiem pewien, że jest to poza zakresem.
paparazzo
3
Oto hipotetyczna odpowiedź: zapłać komuś innemu, kto już wie, co robić. Dzięki milionom nowych użytkowników na sekundę będziesz mieć gotówkę.
whatsisname

Odpowiedzi:

15

Załóżmy, że baza danych nie zawiera nazwy użytkownika „użytkownik1”. Gdy dwóch użytkowników spróbuje zarejestrować się w tym samym momencie jako „użytkownik1”, zaakceptuje to.

Dlaczego miałby to akceptować? Łatwo jest zastosować unikalne ograniczenie, użyć nazwy użytkownika jako klucza podstawowego lub po prostu uruchomić kod aplikacji do odprawy w ramach transakcji.

Absolutnie powinieneś być w stanie użyć transakcji bazy danych, aby użyć bazy danych, aby temu zapobiec. W przeciwnym razie żadna aplikacja nie byłaby w stanie utrzymać niezmienników w danych bazy danych.

Jeśli chodzi o skalowanie, bazy danych wymyśliły już potrzebne technologie, takie jak różne tryby blokowania w zależności od tego, jakiej dokładnie potrzebujesz spójności, rozproszone bazy danych dla wielu serwerów baz danych itp.

DeadMG
źródło
Czy zablokowanie rejestracji nie uniemożliwia innym użytkownikom rejestracji w tym samym czasie?
Addzy K
2
+1, właśnie pobiegłem trochę matematyki, a nawet Facebook średnio tylko kilka rejestracji na sekundę. Oparcie się na własnych ograniczeniach bazy danych powinno zatem wystarczyć.
GrandmasterB
2
@AddzyK: Blokowanie występuje tylko przez krótką chwilę, że baza danych musi wymusić ograniczenia. Tak, inni użytkownicy rejestrujący się jednocześnie muszą czekać w kolejce, ale to oczekiwanie jest bardzo krótkie i rzadko się zdarza, nawet w największych systemach.
Robert Harvey
1
@GrandmasterB Średnie wartości mogą nie przedstawiać pełnej historii tutaj. Przyjąłem na podstawie pytania, że ​​było to do obsługi dużego obciążenia szczytowego - na przykład spisu powszechnego z Australii.
DeadMG,
@AddzyK To może zrobić. Zasadniczo możesz uciec tylko z blokowaniem części stołu. Istnieje wiele schematów radzenia sobie z tym, na przykład odpowiedź gnasher729, ale uważam, że powinieneś być w stanie uzyskać gotowy produkt rozproszonej bazy danych, który poradzi sobie z tym. Nawet jeśli musisz rzucić własny schemat częściowego blokowania, istnieje wiele znanych sposobów radzenia sobie z nim, takich jak DHT.
DeadMG,
7

Istnieje standardowe rozwiązanie tego problemu. Utwórz wielu pracowników, aby dokonać rejestracji. Każde żądanie ma skrót zastosowany do nazwy użytkownika, a skrót określa, który pracownik przetwarza żądanie. W ten sposób nie ma możliwości jednoczesnego przetwarzania dwóch żądań dla tej samej nazwy użytkownika.

W przypadku tego rodzaju liczby zapytań rozważ magazyn rozproszonych wartości kluczy, taki jak ryzyko, zamiast całej bazy danych jako magazyn danych.

Michael Shaw
źródło
2

To jest problem ?

Zezwolenie dwóm użytkownikom na zakończenie rejestracji przy użyciu niepowtarzalnej nazwy użytkownika jest niedopuszczalne, jeśli nazwa użytkownika (a nie adres e-mail użytkownika) jest używana do logowania.

Jeśli nazwa użytkownika nie jest używana do uwierzytelnienia, możesz użyć jakiegoś procesu w tle, aby zidentyfikować i oflagować podwójne (na przykład na podstawie znacznika czasu) i zmusić użytkownika do zmiany swojej nazwy użytkownika przy następnym logowaniu

Tak, to jest problem

Jak pytasz, przypuszczam, że nazwa użytkownika powinna być unikalnym identyfikatorem. Można zastosować następujące podejścia:

  1. Przed: W procesie rejestracji przewidzieć krok, w którym nowy użytkownik musi sprawdzić dostępność swojego imienia i nazwiska. Dokonując tego, zachowaj dostępną nazwę konta ze statusem tymczasowym i identyfikatorem sesji, który pozwoli na zakończenie rejestracji.
  2. Jednocześnie : bardziej ogólnym i elastycznym wariantem odpowiedzi gnasher729 byłoby użycie prostej funkcji skrótu (takiej jak te używane do zarządzania tablicami symboli), aby przypisać identyfikator unikalnemu serwerowi rejestracyjnemu i (i = h (nazwa użytkownika) modulo liczba_serwerów), które będą obsługiwały unikalność w jego ograniczonym / segmentowanym zakresie
  3. Po: Po zakończeniu rejestracji, gdy użytkownik kliknie, registerwyślij zapytanie do bazy danych transakcji, jeśli możesz zdefiniować pole jako unikalne. W przypadku błędu wyślij nieszczęśliwemu użytkownikowi komunikat „Ups, wystąpił problem” i poproś go o wybranie innego identyfikatora.
  4. Asynchroniczny: zarejestruj użytkownika. Ponownie przeczytaj rekord użytkownika tuż po nim, aby upewnić się, że jest niezmieniony, i pojedynczy. Jeśli jest to problem, poproś użytkownika o zmianę (nie tak asynchroniczną), lub wyślij mu wiadomość, że wystąpił problem (asynchroniczny, ale irytujący z perspektywy użytkownika), lub pozwól mu się zarejestrować, ale poproś go o e-mail (jednoznacznie) i zmusić go do zmiany nazwy użytkownika w ramach procedury logowania.
Christophe
źródło
1

Zastanów się, co uważasz za unikalny identyfikator użytkownika. Każdy użytkownik ma już unikalny adres e-mail, więc problem został już rozwiązany. Oczywiście oznacza to, że wielu użytkowników będzie mogło zarejestrować tę samą nazwę, na przykład „Mike Nakis”. Czy jest z tym problem? Jesteś pewny? Na przykład nie jest to problemem na Facebooku. Istnieje wielu użytkowników Facebooka o nazwie „Mike Nakis”. Spójrz na stronę logowania na Facebooku: prosi o „e-mail lub telefon” i „hasło”.

Mike Nakis
źródło
0

Przy milionach użytkowników rejestrujących się w tym samym czasie, korzystasz tylko z 26 x 26 serwerów rejestracyjnych, jednego dla użytkowników rozpoczynających się na aa, jednego dla użytkowników rozpoczynających się na ab i tak dalej. W rezultacie jednocześnie na każdym serwerze rejestrują się tylko tysiące użytkowników. Jeśli nadal nie możesz sobie z tym poradzić, użyj serwerów 26 x 26 x 26.

gnasher729
źródło
5
... a potem twój właściciel produktu chce przejść na
rynek
2
Te same zasady dotyczą ciągów znaków Unicode, o ile mają one znormalizowaną formę, na przykład NFKD. Możesz również przesłać nazwę użytkownika i zastosować ją na podstawie skrótu. Jednak ta odpowiedź to po prostu implementacja własnej rozproszonej bazy danych.
DeadMG,
1
Masz na myśli, że miliony użytkowników rejestrują się jednocześnie w jednym kraju ? W takim przypadku powinni mieć wystarczająco dużo pieniędzy, aby zapłacić więcej za prawdziwe rozwiązanie.
gnasher729,
Mówiąc dokładniej, to dopiero początek tego, jak powstają DHT.
DeadMG,
w jaki sposób rozwiązuje to problem polegający na tym, że dwóch użytkowników rejestruje tę samą nazwę w tym samym czasie - obie nazwy zaczynają się od tych samych dwóch znaków i są obsługiwane przez ten sam serwer rejestracji?
HorusKol,