System powiadomień z sieci społecznościowej

10

tło

Pracuję nad aplikacją dla klienta, która zawiera niektóre funkcje sieci społecznościowych. Początkowo opracowywałem mobilny front-end, ale okoliczności sprawiły, że jestem odpowiedzialny za rozwój back-endu.

Jako ogólny kontekst, nasz system pozwala użytkownikom śledzić innych użytkowników i otrzymywać powiadomienia o tych, których obserwują, jak można oczekiwać od sieci społecznościowej. Zastrzeżenie polega na tym, że tylko niewielki podzbiór (najwyżej kilkaset) użytkowników będzie przestrzegany, przy czym oczekuje się, że większość użytkowników będzie śledzić co najmniej jedną z tych osób.

Po stronie interfejsu użytkownika pojawi się przycisk powiadomienia z numerem, a kliknięcie przycisku spowoduje przejście do ekranu powiadomień.

Problem

Badam strategie wdrażania powiadomień i większość zasobów, które znalazłem, wskazuje na utworzenie jednej lub więcej tabel powiadomień w bazie danych. (Przykładem, który podoba mi się, jest akceptowana odpowiedź tutaj: /programming/9735578/building-a-notification-system ).

Rzeczą, która mnie odrzuca, jest to, że większość strategii powiadomień opartych na bazie danych wymaga wstawienia wiersza dla każdego powiadomienia dla każdego obserwatora. Więc jeśli tysiąc osób śledzi Sally, wstawiamy tysiąc wierszy do odpowiedniej tabeli. Czy to jest skalowalne? Co się stanie, jeśli dojdziemy do punktu, w którym dziesiątki lub setki tysięcy użytkowników śledzą Sally, a ona publikuje kilkadziesiąt postów dziennie?

Mój pierwotny pomysł polegał na tym, aby obsłużyć wszystko za pomocą zapytań: numer na przycisku powiadomień zostałby uzyskany przez żądanie liczenia wierszy treści opublikowanych ostatnio niż podczas ostatniej wizyty na ekranie powiadomień, podczas gdy indywidualne powiadomienia byłyby generowane na podstawie bardziej szczegółowych zapytań kiedy odwiedziłeś ekran powiadomienia. Takie podejście nie wymagałoby zapisywania ani dodatkowej pamięci, ale jest mało elastyczne i prawdopodobnie mocno uderzyłoby w serwer.

USTAWIAĆ

Backend (jak ustalił poprzedni programista) używa CodeIgniter i bazy danych MySQL . Obecnie działa na kiepskim wspólnym koncie hostingowym GoDaddy, ale zakładam (mam nadzieję, że) to zostanie zaktualizowane, zanim przejdziemy do produkcji, a pakiet hostingowy będzie skalowany wraz ze wzrostem liczby użytkowników.

Obecnie naszym jedynym front-endem jest aplikacja mobilna, ale planujemy również później zbudować stronę internetową. W tej chwili nie jestem zainteresowany uzyskiwaniem od serwera aktualizacji wypychanych w czasie rzeczywistym dotyczących powiadomień.

UZUPEŁNIENIE

Nie specjalizuję się w backendach i jestem nad głową w tym dziale. Klient wie o tym i dołożyłem wszelkich starań, aby wyjaśnić zakres projektu tego rodzaju, ale dali jasno do zrozumienia, że ​​w tym momencie nie będą ufać nikomu innemu do pracy nad projektem. Prawdopodobnie mamy jeszcze miesiąc do zrobienia, zanim zaczniemy dodawać testery i będę mógł uzyskać jakiekolwiek pomiary wydajności. Naprawdę nie jestem w stanie oszacować, ilu użytkowników moglibyśmy mieć ani na jakim sprzęcie moglibyśmy być obecni w ciągu najbliższych 5 lat, ale myślę, że klient liczy na setki tysięcy użytkowników lub więcej.

Mam nadzieję, że jest to na tyle specyficzny problem, że można go tutaj opublikować; Mogę to udoskonalić, jeśli zajdzie taka potrzeba. Zapytaj, czy masz jakieś pytania lub pominąłem ważne szczegóły.

tl; dr

  • Czy oparty na bazie danych system powiadomień ma negatywne konsekwencje dla długoterminowej skalowalności, gdy wszyscy użytkownicy śledzą tylko niektóre z tych samych kilkuset osób?
  • Czy istnieje sposób, aby bazy danych powiadomień były sterowane bez potrzeby oddzielnego wiersza powiadomień dla każdego powiadomienia dla każdego obserwatora?
  • Czy system powiadomień oparty wyłącznie na zapytaniach byłby skalowalny, czy miałby jakieś zalety oprócz nie zapisywania żadnych danych w bazie danych?
  • Czy zbyt wcześnie się nad tym zastanawiam? Czy powinienem po prostu zbudować coś, co na razie działa i możemy się martwić o optymalizację, jeśli stanie się to problemem, biorąc pod uwagę, że klient ma ograniczony budżet i nie wiemy jeszcze, czy produkt końcowy będzie popularny?
użytkownik45623
źródło
Czy możesz wygasać powiadomienia? Na przykład usuń wszystko, co ma ponad 2 tygodnie. To powinno mniej więcej zrównoważyć rozmiar tabeli używanej w miarę dojrzewania witryny.
GrandmasterB
To nie będzie problem, bardziej martwiłem się konsekwencjami związanymi z wydajnością blokowania bazy danych i zapisywania 50 000 wpisów w tabeli powiadomień za każdym razem, gdy popularny użytkownik publikuje post.
user45623
Pracowałem nad projektem z podobnym (ale mniejszym) systemem powiadomień. Miałem proces działający w tle, który sprawdzał kolejkę nowych postów i obsługiwał powiadomienia (które w tym przypadku faktycznie wstawiały wiadomość e-mail do drugiej kolejki do wysłania). To nie był czas rzeczywisty, ale ogólnie poradził sobie ze wszystkim w kilka minut.
GrandmasterB

Odpowiedzi:

10

Więc jeśli tysiąc osób śledzi Sally, wstawiamy tysiąc wierszy do odpowiedniej tabeli. Czy to jest skalowalne?

Tak, pod warunkiem, że tabele bazy danych są odpowiednio indeksowane.

Co się stanie, jeśli dojdziemy do punktu, w którym dziesiątki lub setki tysięcy użytkowników śledzą Sally, a ona publikuje kilkadziesiąt postów dziennie?

Będziesz generować kilkadziesiąt lub setki tysięcy rekordów powiadomień dziennie dla Sally, zakładając, że chcesz na bieżąco śledzić każde powiadomienie. Odsetek użytkowników takich jak Sally z tego rodzaju ruchem jest zawsze bardzo mały.

Mój pierwotny pomysł polegał na tym, aby obsłużyć wszystko za pomocą zapytań: numer na przycisku powiadomień zostałby uzyskany przez żądanie liczenia wierszy treści opublikowanych ostatnio niż podczas ostatniej wizyty na ekranie powiadomień, podczas gdy indywidualne powiadomienia byłyby generowane na podstawie bardziej szczegółowych zapytań kiedy odwiedziłeś ekran powiadomienia.

To wydaje się niepotrzebnie skomplikowane. Jeśli potrzebujesz szczegółowych statystyk dotyczących powiadomień, po prostu przechowuj powiadomienia.

Czy oparty na bazie danych system powiadomień ma negatywne konsekwencje dla długoterminowej skalowalności, gdy wszyscy użytkownicy śledzą tylko niektóre z tych samych kilkuset osób?

Właśnie dlatego działa ... niewielka liczba osób zawsze generuje zdecydowaną większość ruchu.

Czy istnieje sposób, aby bazy danych powiadomień były sterowane bez potrzeby oddzielnego wiersza powiadomień dla każdego powiadomienia dla każdego obserwatora?

Tak ... Nie przechowuj powiadomień; po prostu wyślij e-mail z powiadomieniem w stylu „zapomnij”. Lub przechowuj powiadomienia przez określony czas, a następnie je odrzuć. Lub odrzuć każde powiadomienie po jego odczytaniu.

Czy system powiadomień oparty wyłącznie na zapytaniach byłby skalowalny, czy miałby jakieś zalety oprócz nie zapisywania żadnych danych w bazie danych?

Nie jestem pewien, co przez to rozumiesz. Jeśli chcesz wysyłać zapytania do powiadomień, musisz je przechowywać w bazie danych. W przeciwnym razie nie ma nic do zapytania.

Czy zbyt wcześnie się nad tym zastanawiam?

Porozmawiaj z kimś, kto może pomóc Ci zaprojektować właściwie znormalizowaną, indeksowaną bazę danych z odpowiednimi tabelami. Nie widzę powodu, dla którego taka baza danych nie byłaby w stanie skutecznie obsłużyć opisywanych scenariuszy.

Przykład z prawdziwego życia

O ile mi wiadomo, Stack Exchange przechowuje wszystko bez końca, w tym wszystkie powiadomienia. Używają technologii baz danych podobnych do MySql i niektórych technologii buforowania. Podczas gdy ich sprzęt i przestrzeń dyskowa są znaczne, to duży ruch jest dużym problemem.

Robert Harvey
źródło
Wow, do diabła z tym wszystkim! Dzięki, Robert! Baza danych jest znormalizowana, ale nie przeglądałem jeszcze indeksowania. Niestety nie mogę „rozmawiać z kimś, kto może mi pomóc”, ponieważ warunki są ścisłe, że nie mogę omawiać z nikim konkretnych szczegółów projektu, a klient doszedł do tego, że nikomu nie ufa ale ja w projekcie ... Cóż, powinienem być w stanie przeprowadzić badania dotyczące indeksowania. Dzięki!
user45623
1
Ogólne zasady indeksowania: każdy klucz obcy powinien być indeksowany z możliwymi duplikatami. Każdy klucz podstawowy powinien być już zaindeksowany. Pola, które trzeba będzie wyszukać lub zastosować klauzulę WHERE, powinny być indeksowane; to powinno być kilka.
Robert Harvey
1
To jest niepoprawne. To NIE jest skalowalne. Dla każdego „Sally” generujesz N wierszy, w których N jest liczbą użytkowników. Stanie się to problemem szybko, jeśli będziesz mieć rozsądną liczbę użytkowników. 100 „Sallys” publikujących 10 razy do 10 000 użytkowników to 10 milionów wierszy dziennie - nie brzmi to zbyt dobrze, prawda? W rzeczywistości chcesz to odwrócić i utworzyć jeden wiersz dla każdego postu „Sally” i pozwolić wszystkim użytkownikom śledzącym Sally pobrać je zamiast ich osobistej kopii. Oczywiście spowoduje to problemy, jeśli potrzebujesz logiki specyficznej dla użytkownika (np. Agregacja) ...
Ben
1
... wyjaśnienie „unikaj wiersza na post” tutaj jest oczywiście słabym człowiekiem, ponieważ większość systemów wymaga, aby te posty się trzymały. Ponadto nie unikasz zapytań „, ponieważ są skomplikowane”, unikasz ich, ponieważ spowodują one niezrównoważony narzut w miarę skalowania systemu.
Ben