Quali sono le migliori pratiche per costruire qualcosa come un news feed?
Mi piacerebbe ricevere commenti, feedback o approcci alternativi su questa risposta.
Modifica
Per chi è interessato, ho scritto una discreta quantità di codice e ne ho gettato un po' in giro su StackOverflow. Se volete saperne di più o darmi un feedback (molto necessario), siate miei ospiti: http://stackoverflow.com/questions/4162020/how-can-i-improve-this-php-mysql-news-feed
Infondo
Gli utenti nella maggior parte dei siti di social networking sono descrivibili in termini di un grafo sociale. Le relazioni tra gli utenti sono rappresentate da liste di adiacenza. Se Jack e Jill sono amici, si dice che sono adiacenti. Questo è noto come un "bordo" nel grafo.
Determinare l'importanza
Vorrete probabilmente classificare i bordi per importanza piuttosto che semplicemente gli aggiornamenti più recenti, il che significa che avete bisogno di calcolare una sorta di punteggio. L'EdgeRank di Facebook è stato descritto dalla formula ∑e = ue we de, dove ∑e è la somma del rango del bordo, ue è il punteggio di affinità con l'utente che ha creato il bordo, we è il peso per il tipo di contenuto, e de è un fattore di decadimento temporale.
Calcolare il punteggio di affinità di un amico può essere fatto come segue: ∑i = li ni wi, dove ∑i è la somma delle interazioni con quell'amico, li è il tempo trascorso dall'ultima interazione (questo dovrebbe essere pesato in modo che 1 giorno > 30 giorni), ni è il numero di interazioni, e wi è il peso di quelle interazioni. Questo metodo permette di classificare gli amici in un database separato e poi forse mostrare solo dieci aggiornamenti dai dieci amici più vicini, che non è una cattiva idea considerando che pochi di noi probabilmente hanno più amici vicini di così.
Cosa memorizzare
Determinare quali dati memorizzare dipende dal vostro front-end (comprese le attività a cui partecipano i vostri utenti) e dal vostro back-end. Descriverò alcune informazioni generali che puoi memorizzare. I corsivi sono informazioni speciali e opzionali che potrebbero essere necessarie a seconda del vostro schema.
Activity(id, user_id, source_id, activity_type, edge_rank, parent_id, parent_type, data, time)
- user_id - utente che ha generato l'attività
- source_id - record a cui l'attività è collegata
- activity_type - tipo di attività (album fotografico, commento, ecc.))
- edge_rank - il rango per questa particolare attività
- parent_type - il tipo di attività genitore (interesse particolare, gruppo, ecc.)
- parent_id - id chiave primaria per il tipo genitore
- data - oggetto serializzato con meta-dati
Assumendo che stiate usando MySQL come database, potete indicizzare su (user_id, time) e quindi eseguire le vostre query di base. Un esempio di riga di feed per una foto sarebbe:
(id: 1, user_id: 1, source_id: some_source, activity_type:PHOTO, data: (photo_id: 1, photo_name: Getting married)).
In MySQL, le vostre tabelle sarebbero pesantemente denormalizzate poiché l'esecuzione di join danneggia le prestazioni.
Problemi potenziali
- Visibilità - deve mostrare attività interessanti
- Performance - il tempo di ordinamento deve essere minimizzato
- Pubblicazione - molteplici punti di fallimento a seconda del metodo di pubblicazione
Metodi di pubblicazione
Modello "Push", o Fan-out-on-write
Questo metodo comporta la denormalizzazione dei dati delle attività dell'utente'dell'attività dell'utente e spingere i metadati a tutti gli amici dell'utente nel momento in cui si verifica. Si memorizza solo una copia dei dati come nello schema sopra, poi si spingono i puntatori agli amici con i metadati. Il problema con questo metodo è che se hai un grande fan-out (un gran numero di seguaci), corri il rischio che questo si rompa mentre il tuo feed accumula un arretrato. Se andate con questa strategia, rischiate anche un gran numero di ricerche sul disco e di scritture casuali. Vorrai un qualche tipo di archivio dati ottimizzato per la scrittura come Cassandra, HBase, o BigTable.
Modello "Pull", o Fan-out-on-load
Questo metodo comporta il mantenimento in memoria di tutti i dati delle attività recenti e l'estrazione (o la scansione) di quei dati nel momento in cui un utente carica la sua home page. I dati non hanno bisogno di essere inviati a tutti gli abbonati non appena accadono, quindi nessun back-log e nessuna ricerca su disco. Il problema con questo metodo è che si può fallire nel generare il news feed di un utente. Per mitigare questo rischio, si dovrebbe avere un meccanismo di fallback in atto che approssimi il feed dell'utente o che serva da buona alternativa.
Alcuni suggerimenti
- Se si usa MySQL, ci si deve assicurare che la tabella delle attività sia il più possibile compatta, le chiavi siano piccole, e che sia indicizzata in modo appropriato.
- Si potrebbe voler usare Redis per un accesso veloce ai dati freschi del flusso di attività. Redis è ottimizzato per la lettura e memorizza tutti i dati in memoria. Questo è un buon approccio per il modello "Push" descritto sopra.
Conclusioni
Anche se questa non è assolutamente una risposta esaustiva, sto cercando di riassumere quante più informazioni possibili. Le mie fonti per questa risposta sono raccolte nei link qui sotto, quindi ogni informazione in questa risposta va purtroppo senza attribuzione diretta. Un ringraziamento speciale, tuttavia, va ad Ari Steinberg per la sua risposta molto dettagliata a Quali sono i problemi di scalabilità da tenere a mente durante lo sviluppo di un feed di un social network?
Come ho detto all'inizio, mi piacerebbe ricevere commenti, feedback o approcci alternativi su questa risposta.
Fonti
- http://stackoverflow.com/questions/202198/whats-the-best-manner-of-implementing-a-social-activity-stream
- http://stackoverflow.com/questions/1342741/alternatives-to-traditional-relational-databases-for-activity-streams
- Quali sono i problemi di scalabilità da tenere a mente durante lo sviluppo di un feed del social network?
- http://stackoverflow.com/questions/1443960/how-to-implement-the-activity-stream-in-a-social-network
- http://stackoverflow.com/questions/1236511/php-mysql-activity-ala-facebook
- http://stackoverflow.com/questions/762490/how-do-social-networking-websites-compute-friends-updates
- http://stackoverflow.com/questions/2214955/delivering-activity-feed-items-in-a-moderately-scalable-way
- http://stackoverflow.com/questions/1169173/best-way-to-get-friends-actions-for-a-social-network-php-mysql
- http://stackoverflow.com/questions/2835075/php-news-feed-database-design
- http://stackoverflow.com/questions/1167149/user-actions-like-social-networks-facebook-myspace-all-big-ones
- http://stackoverflow.com/questions/2757270/how-to-do-comments-in-activity-stream-like-facebook
- http://stackoverflow.com/questions/762490/how-does-social-networking-websites-compute-friends-updates
Articoli simili
- Come funzionano gli algoritmi dei news feed?
- Quali sono le migliori pratiche per condividere un punteggio di gioco attuale sui social media (Facebook, Twitter, Google+) per un gioco Android?
- Le persone di successo tengono davvero traccia del tempo e quali sono le migliori pratiche per il time tracking?
- Quali sono le pratiche necessarie per vendere o comprare un telefono usato?