Apa cara terbaik menerapkan aliran aktivitas sosial? [Tutup]


265

Saya tertarik mendengar pendapat Anda tentang cara terbaik menerapkan aliran aktivitas sosial (Facebook adalah contoh paling terkenal). Masalah / tantangan yang terlibat adalah:

  • Berbagai jenis kegiatan (posting, komentar ..)
  • Berbagai jenis objek (pos, komentar, foto ..)
  • 1-n pengguna yang terlibat dalam peran yang berbeda ("Pengguna x membalas komentar Pengguna pada pos Z Pengguna")
  • Tampilan berbeda dari item aktivitas yang sama ("Anda berkomentar .." vs. "teman Anda x berkomentar" vs "pengguna x berkomentar .." => 3 representasi dari aktivitas "komentar")

.. dan beberapa lagi, terutama jika Anda membawanya ke tingkat kecanggihan tinggi, seperti yang dilakukan Facebook, misalnya, menggabungkan beberapa item aktivitas menjadi satu ("pengguna x, y dan z mengomentari foto itu"

Setiap pemikiran atau petunjuk tentang pola, makalah, dll tentang pendekatan yang paling fleksibel, efisien dan kuat untuk menerapkan sistem, model data, dll. Akan dihargai.

Meskipun sebagian besar masalah adalah platform-agnostik, kemungkinan saya akhirnya menerapkan sistem seperti itu di Ruby on Rails

Jawaban:


143

Saya telah menciptakan sistem seperti itu dan saya mengambil pendekatan ini:

Tabel database dengan kolom berikut: id, userId, tipe, data, waktu.

  • userId adalah pengguna yang menghasilkan aktivitas
  • tipe adalah jenis kegiatan (mis. Menulis posting blog, menambahkan foto, mengomentari foto pengguna)
  • data adalah objek berseri dengan meta-data untuk aktivitas di mana Anda dapat memasukkan apa pun yang Anda inginkan

Ini membatasi pencarian / pencarian, yang dapat Anda lakukan di umpan, untuk pengguna, jenis waktu dan aktivitas, tetapi dalam umpan aktivitas tipe facebook, ini tidak benar-benar membatasi. Dan dengan indeks yang benar di atas meja pencarian cepat .

Dengan desain ini Anda harus memutuskan metadata apa yang harus dimiliki setiap jenis acara. Misalnya aktivitas umpan untuk foto baru dapat terlihat seperti ini:

{id:1, userId:1, type:PHOTO, time:2008-10-15 12:00:00, data:{photoId:2089, photoName:A trip to the beach}}

Anda dapat melihat bahwa, meskipun nama foto pastinya disimpan di beberapa tabel lain yang berisi foto-foto itu, dan saya dapat mengambil namanya dari sana, saya akan menduplikat nama tersebut di bidang metadata, karena Anda tidak ingin melakukan bergabung dengan tabel database lain jika Anda ingin kecepatan. Dan untuk menampilkan, katakanlah 200, acara yang berbeda dari 50 pengguna yang berbeda, Anda perlu kecepatan.

Kemudian saya memiliki kelas yang memperluas kelas FeedActivity dasar untuk merender berbagai jenis entri aktivitas. Pengelompokan peristiwa akan dibangun dalam kode rendering juga, untuk menjauhkan kompleksitas dari database.


3
Yap, itu benar. Akhir-akhir ini saya telah menggunakan MongoDB ( mongodb.org ) di beberapa proyek, yang pendekatan schemaless membuatnya sangat cocok untuk membuat aliran aktivitas sosial berkinerja baik yang mengikuti desain ini.
heyman

6
TheApprentice: Yap, Anda mungkin ingin memasukkan bidang nama pengguna juga. Dalam sistem kami, kami hanya menampilkan acara yang dihasilkan oleh teman pengguna, dan saya yakin kami sudah memiliki peta nama pengguna-> pengguna- di memori teman, jadi mencari nama pengguna tidak memerlukan GABUNG dan cepat.
heyman

2
Anda harus menangani kasing itu secara manual. Mungkin paling baik melakukannya ketika foto dihapus (cari item umpan di umpan pengguna, dan hapus / perbarui).
heyman

21
Saya tidak mengerti apa yang hebat dari jawaban ini? Bagaimana cara membuat tabel sederhana diterjemahkan ke umpan aktivitas berbobot yang mirip dengan facebook? Yang dia lakukan hanyalah menyimpan semua aktivitas. Yang masih menyisakan pertanyaan tentang bagaimana mengubah tabel data menjadi umpan aktivitas dinamis tertimbang?
ChuckKelly

4
@ ChuckKelly: Jika saya ingat dengan benar, kembali pada 2008, ketika saya menulis jawabannya, umpan Facebook tidak berbobot sama sekali. Itu hanya umpan kronologis dengan semua aktivitas dari teman Anda.
heyman

117

Ini adalah presentasi yang sangat bagus yang menguraikan bagaimana Etsy.com merancang aliran aktivitas mereka. Ini adalah contoh terbaik yang saya temukan pada topik, meskipun tidak spesifik untuk rails.

http://www.slideshare.net/danmckinley/etsy-activity-feeds-architecture


21
^^ Karena Anda harus kembali ke SO setelah mengunjungi situs. lol
Stephen Corwin

1
Presentasi hebat yang menjelaskan secara terperinci bagaimana sistem bekerja pada situs web dengan lalu lintas nyata.
ramirami

44

Kami telah membuka sumber pendekatan kami: https://github.com/tschellenbach/Stream-Framework Saat ini perpustakaan sumber terbuka terbesar ditujukan untuk menyelesaikan masalah ini.

Tim yang sama yang membangun Stream Framework juga menawarkan API yang dihosting, yang menangani kompleksitas untuk Anda. Lihat getstream.io Ada klien yang tersedia untuk Node, Python, Rails dan PHP.

Selain itu lihat pos skalabilitas tinggi ini jika kami menjelaskan beberapa keputusan desain yang terlibat: http://highscalability.com/blog/2013/10/28/design-decisions-for-scaling-your-high-traffic- feeds.html

Tutorial ini akan membantu Anda mengatur sistem seperti umpan Pinterest menggunakan Redis. Cukup mudah untuk memulai.

Untuk mempelajari lebih lanjut tentang desain umpan, saya sangat merekomendasikan untuk membaca beberapa artikel yang menjadi dasar Feedly:

Meskipun Stream Framework berbasiskan Python, itu tidak akan terlalu sulit untuk digunakan dari aplikasi Ruby. Anda bisa menjalankannya sebagai layanan dan menempelkan http API kecil di depannya. Kami sedang mempertimbangkan untuk menambahkan API untuk mengakses Feedly dari bahasa lain. Saat ini Anda harus memainkan peran Anda sendiri.


19

Masalah terbesar dengan aliran acara adalah visibilitas dan kinerja; Anda perlu membatasi acara yang ditampilkan hanya yang menarik untuk pengguna tertentu itu, dan Anda harus menjaga jumlah waktu yang diperlukan untuk memilah dan mengidentifikasi acara-acara tersebut dapat dikelola. Saya telah membangun jaringan sosial yang bertubuh kecil; Saya menemukan bahwa pada skala kecil, menyimpan tabel "peristiwa" dalam database berfungsi, tetapi itu akan menjadi masalah kinerja di bawah beban moderat.

Dengan aliran pesan dan pengguna yang lebih besar, mungkin lebih baik menggunakan sistem pesan, tempat acara dikirim sebagai pesan ke profil individual. Ini berarti bahwa Anda tidak dapat dengan mudah berlangganan aliran acara orang dan melihat acara sebelumnya dengan sangat mudah, tetapi Anda hanya merender sekelompok kecil pesan ketika Anda perlu merender aliran untuk pengguna tertentu.

Saya percaya ini adalah cacat desain asli Twitter- Saya ingat pernah membaca bahwa mereka memukul database untuk menarik dan menyaring acara mereka. Ini semua berhubungan dengan arsitektur dan tidak ada hubungannya dengan Rails, yang (sayangnya) melahirkan meme "ruby tidak skala". Baru-baru ini saya melihat presentasi di mana pengembang menggunakan Simple Queue Service Amazon sebagai backend perpesanan mereka untuk aplikasi seperti twitter yang akan memiliki kemampuan penskalaan yang jauh lebih tinggi - mungkin layak untuk melihat ke SQS sebagai bagian dari sistem Anda, jika beban Anda cukup tinggi .


Tim, apakah Anda ingat nama presentasi atau pembawa acara?
Danita

itu di presentasi Ignite Boston dari Oreilly and Associate, baik nomor 3 atau 4. Saya percaya presenter punya buku tentang skala RoR dengan Oreilly. Maaf saya tidak bisa lebih spesifik!
Tim Howland

Terima kasih Tim :) Ngomong-ngomong, apa maksudmu dengan "jejaring sosial yang kecil"? Berapa banyak pengguna, atau pengguna aktif pada waktu tertentu?
Danita

3
Jika ada yang membutuhkannya, saya pikir ini adalah presentasi yang dibicarakan oleh Tim: "Dan Chak - Memperbesar
Danita

Bertubuh kecil dalam hal ini adalah sedemikian rupa sehingga "pilih * dari peristiwa di mana peristiwa. Dapat dilihat untuk pengguna ini" mengembalikan hasil dalam waktu kurang dari satu detik atau dua angka beberapa ratus ribu baris nilai peristiwa.
Tim Howland

12

Jika Anda bersedia menggunakan perangkat lunak terpisah, saya sarankan server Graphity yang memecahkan masalah untuk stream aktivitas (dibuat di atas basis data grafik neo4j).

Algoritme telah diimplementasikan sebagai server REST mandiri sehingga Anda dapat meng-host server Anda sendiri untuk mengirimkan aliran aktivitas: http://www.rene-pickhardt.de/graphity-server-for-social-activity-streams-released-gplv3 /

Di kertas dan patokan saya menunjukkan bahwa mengambil aliran berita hanya tergantung linier pada jumlah item yang ingin Anda ambil tanpa redundansi yang akan Anda dapatkan dari mendenormalkan data:

http://www.rene-pickhardt.de/graphity-an-efisien-graph-model-for-retrieving-the-top-k-news-feeds-for-users-in-social-networks/

Pada tautan di atas, Anda menemukan screencast dan patokan pendekatan ini (menunjukkan bahwa grafik mampu mengambil lebih dari 10k stream per detik).


10

Saya mulai menerapkan sistem seperti ini kemarin, di sinilah saya harus ...

Saya membuat kelas StreamEvent dengan properti ID , ActorId , TypeId , Date , ObjectId dan hashtable dari pasangan key / value Details tambahan . Hal ini diwakili dalam database oleh StreamEvent meja ( Id , ActorId , typeid , Tanggal , ObjectId ) dan StreamEventDetails meja ( StreamEventId , DetailKey , DetailValue ).

The ActorId , typeid dan ObjectId memungkinkan untuk acara Subyek-Verb-Obyek yang akan diambil (dan kemudian bertanya). Setiap tindakan dapat mengakibatkan beberapa instance StreamEvent dibuat.

Saya kemudian telah membuat sub-kelas untuk StreamEvent setiap jenis acara, misalnya LoginEvent , PictureCommentEvent . Setiap subclass ini memiliki lebih banyak properti konteks spesifik seperti PictureId , ThumbNail , CommenText , dll (apa pun yang diperlukan untuk acara tersebut) yang sebenarnya disimpan sebagai pasangan kunci / nilai dalam tabel hashtable / StreamEventDetail.

Ketika menarik peristiwa ini kembali dari database saya menggunakan metode pabrik (berdasarkan TypeId ) untuk membuat kelas StreamEvent yang benar.

Setiap subclass dari StreamEvent memiliki metode Render ( context As StreamContext ) yang menampilkan acara ke layar berdasarkan kelas StreamContext yang diteruskan . Kelas StreamContext memungkinkan opsi untuk diatur berdasarkan konteks tampilan. Jika Anda melihat Facebook misalnya, umpan berita Anda di beranda mencantumkan nama lengkap (dan tautan ke profil mereka) dari semua orang yang terlibat dalam setiap tindakan, sedangkan melihat umpan teman, Anda hanya melihat nama depan mereka (tetapi nama lengkap aktor lain) .

Saya belum menerapkan umpan agregat (rumah Facebook) tetapi saya membayangkan saya akan membuat tabel AggregateFeed yang memiliki bidang UserId , StreamEventId yang diisi berdasarkan beberapa jenis 'Hmmm, Anda mungkin menemukan ini algoritma yang menarik'.

Setiap komentar akan sangat dihargai.


Saya bekerja pada sistem seperti ini, saya sangat tertarik dengan pengetahuan tentang itu, apakah Anda pernah menyelesaikannya?
JasonDavis

Jawaban bagus! Pemisahan keprihatinan yang sangat baik, bersih dan elegan!
Mosh

Ini awal yang bagus! Ini sangat mirip dengan bagaimana saya mulai menerapkan aliran pertama saya. Namun, begitu Anda mencapai umpan agregat, semuanya mulai menjadi rumit dengan cepat. Anda benar bahwa Anda memerlukan algoritma yang kuat. Pencarian saya membawa saya ke algoritma Rene Pickhardt (dia membicarakannya dalam jawabannya di sini), yang kemudian saya implementasikan ke dalam layanan saya sendiri, yang sekarang bersifat komersial (lihat collabinate.com dan jawaban saya tentang pertanyaan ini untuk informasi lebih lanjut).
Mafuba

10
// satu entri per peristiwa aktual
acara {
  id, cap waktu, jenis, data
}

// satu entri per peristiwa, per umpan yang berisi peristiwa itu
events_feeds {
  event_id, feed_id
}

Saat acara dibuat, tentukan feed mana yang muncul dan tambahkan ke acara_feeds. Untuk mendapatkan umpan, pilih dari events_feeds, bergabunglah dalam acara, pesan berdasarkan stempel waktu. Penyaringan dan agregasi kemudian dapat dilakukan pada hasil permintaan itu. Dengan model ini, Anda dapat mengubah properti acara setelah pembuatan tanpa kerja ekstra.


1
Misalkan orang lain ditambahkan sebagai teman setelah acara ditambahkan, yang perlu melihat acara ini di feed mereka? maka ini tidak akan berhasil
Joshua Kissoon

8

Jika Anda memutuskan untuk menerapkan di Rails, mungkin Anda akan menemukan plugin berikut ini bermanfaat:

ActivityStreams: http://github.com/face/activity_streams/tree/master

Jika tidak ada yang lain, Anda akan bisa melihat implementasi, baik dari segi model data, serta API yang disediakan untuk mendorong dan menarik kegiatan.


6

Saya memiliki pendekatan yang mirip dengan heyman - tabel denormalized yang berisi semua data yang akan ditampilkan dalam aliran aktivitas yang diberikan. Ini berfungsi dengan baik untuk situs kecil dengan aktivitas terbatas.

Seperti disebutkan di atas, kemungkinan akan menghadapi masalah skalabilitas saat situs tumbuh. Secara pribadi, saya tidak khawatir tentang masalah penskalaan saat ini. Saya akan khawatir tentang itu di lain waktu.

Facebook jelas telah melakukan penskalaan yang bagus jadi saya akan merekomendasikan Anda membaca blog teknik mereka, karena memiliki banyak konten hebat -> http://www.facebook.com/notes.php?id=9445547199

Saya telah mencari solusi yang lebih baik daripada tabel denormalized yang saya sebutkan di atas. Cara lain yang saya temukan untuk mencapai hal ini adalah menyingkat semua konten yang akan ada dalam aliran aktivitas tertentu menjadi satu baris. Ini dapat disimpan dalam XML, JSON, atau format serial yang dapat dibaca oleh aplikasi Anda. Proses pembaruan juga sederhana. Setelah aktivitas, tempatkan aktivitas baru ke dalam antrian (mungkin menggunakan Amazon SQS atau yang lainnya) dan kemudian terus-menerus mengumpulkan antrian untuk item berikutnya. Ambil item itu, uraikan, dan tempatkan isinya di objek umpan yang sesuai yang disimpan dalam database.

Hal yang baik tentang metode ini adalah Anda hanya perlu membaca satu tabel basis data setiap kali umpan tertentu diminta, daripada mengambil serangkaian tabel. Selain itu, ini memungkinkan Anda untuk mempertahankan daftar aktivitas terbatas karena Anda dapat menghapus item aktivitas terlama setiap kali Anda memperbarui daftar.

Semoga ini membantu! :)


Pikiranku tepat, aku hanya membutuhkan validasi pikiranku yang mungkin kudapat sekarang, tepuk tangan!
Sohail


3

Saya pikir Plurk pendekatan menarik: mereka menyediakan seluruh garis waktu Anda dalam format yang sangat mirip dengan grafik saham Google Finance.

Mungkin pantas untuk melihat Ning untuk melihat bagaimana jaringan jejaring sosial bekerja. The pengembang halaman terlihat sangat membantu.


2

Saya menyelesaikan ini beberapa bulan yang lalu, tetapi saya pikir implementasi saya terlalu mendasar.
Saya membuat model berikut:

HISTORY_TYPE

ID           - The id of the history type
NAME         - The name (type of the history)
DESCRIPTION  - A description

HISTORY_MESSAGES

ID
HISTORY_TYPE - A message of history belongs to a history type
MESSAGE      - The message to print, I put variables to be replaced by the actual values

HISTORY_ACTIVITY

ID
MESSAGE_ID    - The message ID to use
VALUES        - The data to use

Contoh

MESSAGE_ID_1 => "User %{user} created a new entry"
ACTIVITY_ID_1 => MESSAGE_ID = 1, VALUES = {user: "Rodrigo"}

2

Setelah menerapkan stream aktivitas untuk mengaktifkan fitur umpan sosial, microblog, dan kolaborasi di beberapa aplikasi, saya menyadari bahwa fungsionalitas dasar cukup umum dan dapat diubah menjadi layanan eksternal yang Anda gunakan melalui API. Jika Anda sedang membangun arus menjadi aplikasi produksi dan tidak memiliki kebutuhan yang unik atau sangat kompleks, memanfaatkan layanan yang sudah terbukti mungkin merupakan cara terbaik untuk melakukannya. Saya pasti akan merekomendasikan ini untuk aplikasi produksi daripada menggulirkan solusi sederhana Anda sendiri di atas database relasional.

Perusahaan saya Collabinate ( http://www.collabinate.com ) tumbuh dari realisasi ini, dan kami telah menerapkan engine stream aktivitas berkinerja tinggi yang dapat diskalakan di atas basis data grafik untuk mencapainya. Kami sebenarnya menggunakan varian dari algoritma Graphity (diadaptasi dari karya awal @RenePickhardt yang juga memberikan jawaban di sini) untuk membangun mesin.

Jika Anda ingin meng-host mesin sendiri atau memerlukan fungsionalitas khusus, kode inti sebenarnya adalah open source untuk tujuan non-komersial, jadi Anda dapat melihatnya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.