Jak wdrożyć strumień aktywności w sieci społecznościowej

140

Rozwijam własną sieć społecznościową i nie znalazłem w sieci przykładów realizacji strumienia działań użytkowników ... Na przykład, jak filtrować akcje dla każdego użytkownika? Jak przechowywać wydarzenia akcji? Którego modelu danych i modelu obiektowego mogę używać dla strumienia akcji i dla samych akcji?

Nicolò Martini
źródło
9
powodzenia, to jest niekończące się pytanie, które wszyscy chcemy wiedzieć, jak Facebook to robi, odpowiedź jest bardzo złożona i być może nigdy nie poznamy najbardziej efektywnego sposobu zrobienia tego. Jeśli znajdziesz dobre podejście, prześlij je tutaj, aby inni mogli je zobaczyć, BTW było to omawiane wiele razy w SO, więc po prostu wyszukaj, a znajdziesz kilka wskazówek
JasonDavis
1
Stream Framework jest najczęściej używanym rozwiązaniem: github.com/tschellenbach/Stream-Framework Zobacz także tę listę pakietów: djangopackages.com/grids/g/activities
Thierry
1
Jeśli chodzi o personalizację, opiera się na analityce i uczeniu maszynowym. Zobacz także getstream.io/personalization
Thierry

Odpowiedzi:

241

Podsumowanie : Dla około 1 miliona aktywnych użytkowników i 150 milionów zapisanych działań, utrzymuję to w prostocie:

  • Użyj relacyjnej bazy danych do przechowywania unikalnych działań (1 rekord na działanie / „rzecz, która się wydarzyła”). Uczyń rekordy tak zwartymi, jak to tylko możliwe. Struktura, dzięki której można szybko pobrać pakiet działań według identyfikatora działania lub przy użyciu zestawu identyfikatorów znajomych z ograniczeniami czasowymi.
  • Publikuj identyfikatory działań w Redis za każdym razem, gdy tworzony jest rekord aktywności, dodając identyfikator do listy „strumienia aktywności” dla każdego użytkownika, który jest znajomym / subskrybentem, który powinien zobaczyć działanie.

Zapytaj Redis, aby uzyskać strumień aktywności dla dowolnego użytkownika, a następnie w razie potrzeby pobierz powiązane dane z bazy danych. Wróć do odpytywania bazy danych według czasu, jeśli użytkownik musi przeglądać daleko w czasie (jeśli w ogóle to oferujesz)


Używam zwykłej starej tabeli MySQL do obsługi około 15 milionów działań.

Wygląda mniej więcej tak:

id             
user_id       (int)
activity_type (tinyint)
source_id     (int)  
parent_id     (int)
parent_type   (tinyint)
time          (datetime but a smaller type like int would be better) 

activity_typeinformuje mnie o rodzaju czynności, source_idinformuje o zapisie, z którym jest ona związana. Więc jeśli typ działania oznacza „dodane ulubione”, to wiem, że source_id odnosi się do identyfikatora ulubionego rekordu.

parent_id/ parent_typeSą użyteczne dla mojej aplikacji - mówią mi, jaka działalność jest związana. Gdyby książka została dodana do ulubionych, wtedy parent_id / parent_type powiedziałby mi, że działanie dotyczy książki (typu) z podanym kluczem podstawowym (id)

Indeksuję (user_id, time)i wyszukuję działania, które są user_id IN (...friends...) AND time > some-cutoff-point. Porzucenie identyfikatora i wybranie innego indeksu klastrowego może być dobrym pomysłem - nie eksperymentowałem z tym.

Całkiem podstawowe rzeczy, ale działają, są proste i łatwo się z nimi pracuje, gdy zmieniają się Twoje potrzeby. Ponadto, jeśli nie używasz MySQL, możesz być w stanie zrobić to lepiej pod względem indeksowania.


Aby uzyskać szybszy dostęp do najnowszych działań, eksperymentowałem z Redis . Redis przechowuje wszystkie swoje dane w pamięci, więc nie możesz umieścić tam wszystkich swoich działań, ale możesz przechowywać ich wystarczająco dużo dla większości najczęściej odwiedzanych ekranów w Twojej witrynie. Najnowsze 100 dla każdego użytkownika lub coś w tym rodzaju. Z Redisem w miksie może to wyglądać tak:

  • Utwórz swój rekord aktywności MySQL
  • Dla każdego znajomego użytkownika, który utworzył działanie, umieść identyfikator na jego liście działań w Redis.
  • Przytnij każdą listę do ostatnich X elementów

Usługa Redis jest szybka i oferuje sposób przesyłania poleceń w ramach jednego połączenia - więc przekazanie aktywności 1000 znajomym zajmuje milisekundy.

Bardziej szczegółowe wyjaśnienie tego, o czym mówię, można znaleźć w przykładzie Redis na Twitterze: http://redis.io/topics/twitter-clone

Aktualizacja luty 2011 Mam w tej chwili 50 milionów aktywnych działań i niczego nie zmieniłem. Jedną fajną rzeczą w robieniu czegoś podobnego jest to, że używa kompaktowych, małych rzędów. Planuję wprowadzić pewne zmiany, które obejmowałyby znacznie więcej działań i więcej zapytań związanych z tymi działaniami, i na pewno będę używać Redis, aby przyspieszyć działanie. Używam Redis w innych obszarach i naprawdę dobrze działa w przypadku niektórych problemów.

Aktualizacja, lipiec 2014 r. Mamy około 700 tys. Aktywnych użytkowników miesięcznie. Od kilku lat używam Redis (zgodnie z opisem na liście punktowanej) do przechowywania ostatnich 1000 identyfikatorów aktywności dla każdego użytkownika. W systemie jest zwykle około 100 milionów rekordów aktywności i nadal są one przechowywane w MySQL i nadal mają ten sam układ. Te rekordy pozwalają nam uciec z mniejszą ilością pamięci Redis, służą jako zapis danych o aktywności i używamy ich, jeśli użytkownicy muszą cofnąć się w czasie, aby coś znaleźć.

Nie było to sprytne ani szczególnie interesujące rozwiązanie, ale dobrze mi służyło.

przegrany
źródło
2
+1 dla Redis. v2 wykorzystuje pamięć wirtualną, więc powinno być możliwe całkowite poleganie na Redis
Stagas
16
Jeśli istnieje wiele źródeł aktywności (dodawanie, komentowanie, polubienie itp.), Jak połączyć tę tabelę z rzeczywistymi działaniami? Czy używasz wielu złączeń lewych (każde dla tabeli aktywności)?
Ali Shakiba,
1
@casey Echoing Pytanie @JohnS - jak wykonujesz zadanie JOINna różnych activity_typestołach? Czy te połączenia są drogie pod względem wydajności?
Rob Sobers,
1
Czy ktoś ma odpowiedź na pytanie Johna dotyczące „DOŁĄCZ”. Czy ktoś może opublikować link, w którym można to wyjaśnić? Muszę zrobić podobnie i byłoby to dla mnie bardzo pomocne.
Waseem
3
Brak połączeń. Jedno zapytanie na unikalne, activity_typeaby uzyskać inne potrzebne dane.
pokonany
21

To jest moja implementacja strumienia aktywności przy użyciu mysql. Istnieją trzy klasy: Activity, ActivityFeed, Subscriber.

Aktywność reprezentuje wpis aktywności, a jej tabela wygląda następująco:

id
subject_id
object_id
type
verb
data
time

Subject_idto identyfikator obiektu wykonującego akcję, object_ididentyfikator obiektu, który otrzymuje akcję. typei verbopisuje samą akcję (na przykład, jeśli użytkownik doda komentarz do artykułu, będzie to odpowiednio „komentarz” i „utworzony”), dane zawierają dodatkowe dane w celu uniknięcia łączenia (na przykład mogą zawierać nazwę tematu i nazwisko, tytuł i adres artykułu, treść komentarza itp.).

Każde działanie należy do co najmniej jednego źródła działań i są one powiązane tabelą, która wygląda następująco:

feed_name
activity_id

W mojej aplikacji mam jeden kanał dla każdego użytkownika i jeden kanał dla każdego elementu (zwykle artykuły na blogu), ale mogą to być, co chcesz.

Subskrybent jest zwykle użytkownikiem Twojej witryny, ale może to być również dowolny obiekt w Twoim modelu obiektowym (na przykład artykuł może być zasubskrybowany w treści źródła treści jego twórcy).

Każdy subskrybent należy do co najmniej jednego źródła ActivityFeed i, podobnie jak powyżej, są one powiązane tabelą linków tego rodzaju:

feed_name
subscriber_id
reason

reasonPole tutaj wyjaśnia dlaczego abonent subskrypcji kanału. Na przykład, jeśli użytkownik doda zakładkę do posta na blogu, powodem jest „zakładka”. Pomaga mi to później w filtrowaniu działań pod kątem powiadomień dla użytkowników.

Aby pobrać aktywność dla subskrybenta, wykonuję proste połączenie trzech tabel. Łączenie jest szybkie, ponieważ wybieram kilka działań dzięki WHEREwarunkowi, który wygląda jak teraz - time > some hours. Unikam innych łączeń dzięki polu danych w Tabeli aktywności.

Dalsze wyjaśnienia w reasonterenie. Jeśli na przykład chcę filtrować akcje dla powiadomień e-mail do użytkownika, a użytkownik dodał zakładkę do posta na blogu (i subskrybuje kanał postów z powodem `` zakładka ''), nie chcę, aby użytkownik otrzymał powiadomienia e-mail o działaniach dotyczących tego elementu, a jeśli komentuje post (a więc subskrybuje kanał wiadomości z uzasadnieniem „komentarz”), chcę, aby był powiadamiany, gdy inni użytkownicy dodają komentarze do tego samego postu. Pole powodu pomaga mi w tej dyskryminacji (zaimplementowałem to poprzez klasę ActivityFilter), wraz z preferencjami powiadomień użytkownika.

Nicolò Martini
źródło
Nicolo martini chciałem dodać komentarz do działania i pokazać go pod nim, jak to możliwe z twoją strukturą? powinienem dodać kolejną tabelę, czy po prostu użyć tego samego, jeśli to samo, jakie są twoje sugestie?
Basit
Jak wygląda ta implementacja? Jakieś testy na dużych stołach?
Joshua F. Rountree
16

Istnieje obecny format strumienia aktywności, który jest opracowywany przez grupę dobrze znanych osób.

http://activitystrea.ms/ .

Zasadniczo, każda czynność ma aktora (który wykonuje czynność), czasownik (czynność czynności), przedmiot (na którym aktor wykonuje) i cel.

Na przykład: Max opublikował link do ściany Adama.

Ich specyfikacja JSON osiągnęła wersję 1.0 w momencie pisania tego tekstu, która pokazuje wzorzec aktywności, którą możesz zastosować.

Ich format został już przyjęty przez BBC, Gnip, Google Buzz Gowalla, IBM, MySpace, Opera, Socialcast, Superfeedr, TypePad, Windows Live, YIID i wiele innych.

Sơn Trần-Nguyễn
źródło
cześć @sntran Wiem, że ten post był lata temu, ale mam pytanie dotyczące strumienia aktywności. Czy jest sposób, w jaki możesz pomóc?
hiswendy
Pewnie. Jakie jest Twoje pytanie?
Sơn Trần-Nguyễn
Moje pytanie zostało umieszczone tutaj! łącze . Myślę, że mam podstawowe pojęcie o strumieniu aktywności, ale naprawdę nie jestem pewien, jak go zaimplementować (tj. Czy mam używać angular lub node.js?). I stamtąd, jak właściwie TWORZĘ strumień aktywności za pomocą przychodzące API JSON? To takie podstawowe pytania, ale nie mogłem znaleźć odpowiedzi w Internecie. Jeśli możesz pomóc, byłbym naprawdę wdzięczny. Dziękuję Ci!
hiswendy
13

Myślę, że wyjaśnienie, jak działa system powiadomień na dużych stronach internetowych, można znaleźć w pytaniu o przepełnienie stosu, w jaki sposób serwisy społecznościowe obliczają aktualizacje znajomych? , w odpowiedzi Jeremy Wall . Sugeruje użycie Message Qeue i wskazuje dwa programy open source, które ją implementują:

  1. RabbitMQ
  2. Apache QPid

Zobacz też pytanie Jaki jest najlepszy sposób realizacji strumienia aktywności społecznej?

Nicolò Martini
źródło
1

Absolutnie potrzebujesz wydajnej i rozproszonej kolejki wiadomości. Ale to nie koniec, będziesz musiał podjąć decyzje, co przechowywać jako dane trwałe, a co przejściowe itp.

Zresztą to naprawdę trudne zadanie, przyjacielu, jeśli szukasz wydajnego i skalowalnego systemu. Ale oczywiście niektórzy hojni inżynierowie podzielili się swoimi doświadczeniami w tej sprawie. LinkedIn ostatnio udostępnił swój system kolejki wiadomości Kafka open source. Wcześniej Facebook udostępnił Scribe społeczności open source. Kafka jest napisana w Scali i na początku jej uruchomienie zajmuje trochę czasu, ale testowałem z kilkoma serwerami wirtualnymi. To jest naprawdę szybkie.

http://blog.linkedin.com/2011/01/11/open-source-linkedin-kafka/

http://incubator.apache.org/kafka/index.html

Cagatay Kalan
źródło
0

Zamiast tworzyć własną, możesz poszukać usługi strony trzeciej używanej za pośrednictwem interfejsu API. Założyłem jeden o nazwie Collabinate ( http://www.collabinate.com ), który ma zaplecze graficznej bazy danych i kilka dość wyrafinowanych algorytmów do obsługi dużych ilości danych w sposób bardzo współbieżny i wydajny. Chociaż nie ma tak szerokiego zakresu funkcji, jak Facebook lub Twitter, jest więcej niż wystarczający w większości przypadków użycia, w których musisz wbudować strumienie aktywności, kanały społecznościowe lub funkcję mikroblogowania w aplikacji.

Mafuba
źródło