Sosyal etkinlik akışını uygulamanın en iyi yolu nedir? [kapalı]


265

Sosyal etkinlik akışını uygulamanın en iyi yolu olan düşüncelerinizi duymakla ilgileniyorum (Facebook en ünlü örnektir). İlgili sorunlar / zorluklar:

  • Farklı faaliyet türleri (yayınlama, yorum yapma ..)
  • Farklı nesne türleri (yazı, yorum, fotoğraf ..)
  • Farklı rollerde yer alan 1-n kullanıcı ("x kullanıcısı, Kullanıcının Z yayınındaki yorumuna yanıt verdi")
  • Aynı etkinlik öğesinin farklı görünümleri ("yorum yaptınız .." vs. "arkadaşınız x yorumladı" vs. "kullanıcı x yorumladı .." => "yorum" etkinliğinin 3 temsili)

.. ve daha fazlası, özellikle Facebook'un yaptığı gibi, örneğin çok sayıda etkinlik öğesini bir araya getirerek ("x, y ve z kullanıcıları bu fotoğrafa yorum yaptı")

Bu tür bir sistemin, veri modelinin, vb. Uygulanmasına yönelik en esnek, verimli ve güçlü yaklaşımlar hakkında kalıplar, kağıtlar, vb. Üzerine düşünceler veya işaretçiler takdir edilecektir.

Sorunların çoğu platformdan bağımsız olsa da, Ruby on Rails üzerinde böyle bir sistemi uygulama şansım var

Yanıtlar:


143

Böyle bir sistem yarattım ve bu yaklaşımı benimsedim:

Şu sütunları içeren veritabanı tablosu: id, userId, tip, veri, zaman.

  • userId , etkinliği oluşturan kullanıcıdır
  • tür , etkinliğin türüdür (ör. blog yazısı yazdı, fotoğraf ekledi, kullanıcının fotoğrafına yorum yaptı)
  • data , istediğiniz her şeyi koyabileceğiniz etkinlik için meta verileri içeren serileştirilmiş bir nesnedir

Bu, feed'lerde, kullanıcılara, zamana ve etkinlik türlerine yapabileceğiniz aramaları / aramaları sınırlar, ancak facebook türü bir etkinlik feed'inde bu gerçekten sınırlayıcı değildir. Ve tablodaki doğru endekslerle aramalar hızlıdır .

Bu tasarımla, her bir etkinlik türünün hangi meta veriyi gerektirmesi gerektiğine karar vermeniz gerekir. Örneğin, yeni bir fotoğraf için feed etkinliği şöyle görünebilir:

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

Gördüğünüz gibi, fotoğrafın adı kesinlikle fotoğrafları içeren başka bir tabloda saklanıyor ve adı oradan alabiliyorum, meta veri alanındaki adı çoğaltacağım, çünkü yapmak istemezsiniz hız istiyorsanız diğer veritabanı tablolarında herhangi bir birleşimler. Ve diyelim ki 200, 50 farklı kullanıcıdan farklı etkinlikleri görüntülemek için hıza ihtiyacınız var.

Sonra farklı türde etkinlik girişleri oluşturmak için temel bir FeedActivity sınıfı genişleten sınıfları var. Olayların gruplandırılması, veritabanından karmaşıklığı uzak tutmak için oluşturma kodunda da oluşturulacaktır.


3
Evet, bu doğru. Son zamanlarda , şematik yaklaşımı bu tasarımı takip eden iyi performans gösteren bir sosyal aktivite akışı oluşturmak için çok uygun hale getiren birkaç projede MongoDB'yi ( mongodb.org ) kullanıyorum .
heyman

6
The Apprentice: Evet, bir kullanıcı adı alanına da atmak isteyebilirsiniz. Sistemimizde, yalnızca bir kullanıcının arkadaşları tarafından oluşturulan etkinlikleri görüntüledik ve inanıyorum ki zaten arkadaşlarının kullanıcı kimliği-> kullanıcı adının bellekte bir haritası vardı, bu yüzden kullanıcı adlarına bakmak bir JOIN gerektirmedi ve hızlıydı.
heyman

2
Bu vakayı manuel olarak ele almanız gerekir. Fotoğraf silindiğinde bunu yapmak en iyisidir (kullanıcının feed'indeki feed öğesini bulun ve silin / güncelleyin).
heyman

21
Bu cevapla ilgili neyin bu kadar harika olduğunu anlamıyorum. Basit bir tablo oluşturmak facebook'a benzer ağırlıklı bir etkinlik feed'ine nasıl dönüşür? Tek yaptığı tüm aktiviteyi saklamak. Hangisi hala bir veri tablosunun dinamik ağırlıklı etkinlik feed'ine dönüştürüleceği sorusunu bırakıyor?
ChuckKelly

4
@ChuckKelly: Doğru hatırlıyorsam, 2008'de, cevabı yazdığımda, Facebook beslemesi hiç ağırlıklı değildi. Bu sadece arkadaşlarınızın tüm etkinliklerini içeren kronolojik bir beslemeydi.
heyman


44

Yaklaşımımızı açık kaynaklı olarak sunduk: https://github.com/tschellenbach/Stream-Framework Şu anda bu sorunu çözmeyi amaçlayan en büyük açık kaynak kütüphanesi.

Stream Framework'ü oluşturan aynı ekip, sizin için karmaşıklığı ele alan barındırılan bir API da sunar. Getstream.io'ya bir göz atın Düğüm, Python, Rails ve PHP için istemciler vardır.

Ayrıca, tasarımla ilgili bazı kararları açıklıyor olsaydık, bu yüksek ölçeklenebilirlik yayınına bir göz atın: http://highscalability.com/blog/2013/10/28/design-decisions-for-scaling-your-high-traffic- feeds.html

Bu eğitici , Redis kullanarak Pinterest beslemesi gibi bir sistem kurmanıza yardımcı olacaktır. Başlamak oldukça kolaydır.

Feed tasarımı hakkında daha fazla bilgi edinmek için Feedly'nin temel aldığı bazı makaleleri okumanızı şiddetle tavsiye ederim:

Stream Framework Python tabanlı olsa da Ruby uygulamasından kullanmak çok zor olmaz. Basitçe bir hizmet olarak çalıştırabilir ve önüne küçük bir http API yapıştırabilirsiniz. Feedly'ye diğer dillerden erişmek için bir API eklemeyi düşünüyoruz. Şu anda kendi rolünü üstlenmen gerekecek.


19

Etkinlik akışlarıyla ilgili en büyük sorunlar görünürlük ve performans; görüntülenen olayları yalnızca söz konusu kullanıcı için ilginç olanlarla sınırlandırmanız ve bu olayları sıralamak ve yönetilebilir olarak tanımlamak için gereken süreyi tutmanız gerekir. Ufacık bir sosyal ağ kurdum; Ben küçük ölçeklerde, bir "olaylar" tabloyu bir veritabanında tutmak çalışır, ancak orta yük altında bir performans sorunu olur.

Daha büyük bir mesaj ve kullanıcı akışıyla, olayların ayrı ayrı profillere mesaj olarak gönderildiği bir mesajlaşma sistemine gitmek en iyisidir. Bu, insanların etkinlik akışlarına kolayca abone olamayacağınız ve önceki etkinlikleri çok kolay görebileceğiniz anlamına gelir, ancak belirli bir kullanıcı için akışı oluşturmanız gerektiğinde küçük bir grup ileti oluşturursunuz.

Bunun Twitter'ın özgün tasarım hatası olduğuna inanıyorum- Olaylarını çekmek ve filtrelemek için veritabanına isabet ettiklerini hatırlıyorum. Bunun mimariyle ilgisi vardı ve Rails ile ilgisi yoktu (maalesef) "yakut ölçeklemiyor" memünü doğurdu. Kısa süre önce geliştiricinin Amazon'un Basit Kuyruk Hizmetini , çok daha yüksek ölçeklendirme yeteneklerine sahip olan twitter benzeri bir uygulama için mesajlaşma arka planı olarak kullandığı bir sunum gördüm - yükleriniz yeterince yüksekse, SQS'ye sisteminizin bir parçası olarak bakmaya değer olabilir .


Tim, hiç bir zaman sunumun veya sunumcunun adını hatırlıyor musun?
Danita

3 veya 4 numaralı Oreilly ve Associate'in Ignite Boston sunumundaydı. Sunucunun Oreilly ile RoR'yi ölçeklendirme konusunda bir kitabı olduğuna inanıyorum. Üzgünüm daha spesifik olamam!
Tim Howland

Teşekkürler Tim :) Bu arada, "ufacık sosyal ağ" ile ne demek istediniz? Belirli bir zamanda kaç kullanıcı veya etkin kullanıcı var?
Danita

3
Kimsenin ihtiyacı varsa, bu Tim'in konuştuğu sunum olduğunu düşünüyorum: "Dan Chak - Sorunların Boyutuna Ölçeklendirme" radar.oreilly.com/2008/09/ignite-boston-4----videos -uplo.html
Danita

Bu durumda ufacık, "event.in bu kullanıcı için görünür olduğu olaylardan * seçin" ifadesinin, birkaç yüz bin satırlık olay değerinde bir veya iki rakamdan daha az bir sonuç döndürdüğü şekildedir.
Tim Howland

12

Ayrı bir yazılım kullanmak istiyorsanız, etkinlik akışları için sorunu tam olarak çözen Graphity sunucusunu öneririm (neo4j grafik veri tabanının üzerine inşa ederek).

Algoritmalar bağımsız bir REST sunucusu olarak uygulandı, böylece aktivite akışları sağlamak için kendi sunucunuzu barındırabilirsiniz: http://www.rene-pickhardt.de/graphity-server-for-social-activity-streams-released-gplv3 /

Kağıt ve karşılaştırmalı değerlendirmede, haber akışlarını almanın, verileri normalleştirmeden elde edeceğiniz herhangi bir artıklık olmadan almak istediğiniz öğelerin miktarına yalnızca doğrusal bağlı olduğunu gösterdim:

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

Yukarıdaki bağlantıda ekran görüntüleri ve bu yaklaşımın bir karşılaştırmasını bulacaksınız (grafiğin saniyede 10 bin'den fazla akışı alabildiğini gösterir).


10

Dün böyle bir sistem uygulamaya başladım, işte buradayım ...

Bir oluşturulan StreamEvent özellikleri olan sınıf Kimliği , ActorId , TypeId , Tarih , Nesne Kimliği ve ek bir hashtable Detayları anahtar / değer çiftleri. Bu veritabanında temsil edilir StreamEvent tablosu ( İd , ActorId , TypeId , Tarih , Nesne Kimliği ) ve StreamEventDetails tablosu ( StreamEventId , DetailKey , DetailValue ).

ActorId , TypeId ve Nesne Kimliği bir Özne-Fiil-Nesne olay yakalanan (ve daha sonra sorgulanan) olmak üzere izin verir. Her eylem birkaç StreamEvent örneğinin oluşturulmasına neden olabilir.

Sonra StreamEvent her tür olay için bir alt sınıf oluşturdum, örneğin LoginEvent , PictureCommentEvent . Bu alt sınıfların her biri, aslında hashtable / StreamEventDetail tablosunda anahtar / değer çiftleri olarak depolanan PictureId , ThumbNail , CommenText vb. Gibi daha fazla içeriğe özgü özelliklere sahiptir .

Bu olayları veritabanından geri çekerken doğru StreamEvent sınıfını oluşturmak için bir fabrika yöntemi ( TypeId tabanlı ) kullanıyorum.

StreamEvent'in her alt sınıfı , iletilen StreamContext sınıfını temel alarak olayı ekrana gönderen bir Render ( bağlam As StreamContext ) yöntemine sahiptir . StreamContext sınıfı, seçeneklerin görünümün bağlamına göre ayarlanmasına olanak tanır. Örneğin Facebook'a bakarsanız, ana sayfadaki haber feed'inizde her bir eylemde yer alan herkesin tam adları (ve profillerine bağlantılar) listelenirken, bir arkadaşınızın özet akışına baktığınızda yalnızca adlarını (ancak diğer oyuncuların tam adlarını) görürsünüz .

Henüz bir özet akışı (Facebook ana sayfası) uygulamamıştım, ancak bir tür 'Hmmm, bu ilginç bulabilirsiniz' algoritmasına dayalı olarak doldurulmuş UserId , StreamEventId alanlarına sahip bir AggregateFeed tablosu oluşturacağımı hayal ediyorum .

Herhangi bir yorum çok takdir edilecektir.


Bu tür bir sistem üzerinde çalışıyorum, bununla ilgili herhangi bir bilgi ile çok ilgileniyorum, hiç bitirdin mi?
JasonDavis

Mükemmel cevap! Endişelerin mükemmel ayrılması, temiz ve zarif!
Mosh

Bu iyi bir başlangıç! İlk akışımı uygulamaya nasıl başladığımla çok benzer. Ancak, toplu feed'e ulaştığınızda, işler karmaşıklaşmaya başlar. Sağlam bir algoritmaya ihtiyacınız olduğu konusunda haklısınız. Araştırmam beni Rene Pickhardt'ın algoritmasına (burada cevabından bahsediyor) yönlendirdi, bu da şimdi ticari olan kendi hizmetime uyguladım (bkz. Collabinate.com ve daha fazla bilgi için bu soruya cevabım).
Mafuba

10
// her gerçek etkinlik için bir giriş
Etkinlikler {
  id, zaman damgası, tür, veri
}

// o etkinliği içeren her feed için etkinlik başına bir giriş
events_feeds {
  event_id, feed_id
}

Etkinlik oluşturulduğunda, hangi özet akışlarında göründüğüne karar verin ve bunları feed_feeds'e ekleyin. Feed almak için events_feeds arasından seçim yapın, etkinliklere katılın, zaman damgasına göre sıralayın. Filtreleme ve toplama daha sonra bu sorgunun sonuçları üzerinde yapılabilir. Bu modelle, oluşturulduktan sonra ekstra çalışma gerektirmeden etkinlik özelliklerini değiştirebilirsiniz.


1
Etkinlik eklendikten sonra başka birinin arkadaş olarak eklendiğini varsayalım, bu etkinliği feed'lerinde görmesi gerekiyor mu? bu işe yaramaz
Joshua Kissoon


6

Heyman'a benzer bir yaklaşımım vardı - belirli bir aktivite akışında görüntülenecek tüm verileri içeren denormalize bir tablo. Sınırlı aktiviteye sahip küçük bir site için iyi çalışır.

Yukarıda belirtildiği gibi, site büyüdükçe ölçeklenebilirlik sorunlarıyla karşılaşılması muhtemeldir. Şahsen, şu anda ölçeklendirme sorunları hakkında endişelenmiyorum. Daha sonra endişeleneceğim.

Facebook açık bir şekilde büyük bir ölçekleme işi yaptı, bu yüzden bir sürü harika içeriğe sahip olduğu için mühendislik bloglarını okumanızı tavsiye ederim -> http://www.facebook.com/notes.php?id=9445547199

Yukarıda bahsettiğim denormalize tablodan daha iyi çözümler araştırıyorum. Bunu başarmanın başka bir yolu, belirli bir etkinlik akışında olacak tüm içeriği tek bir satırda yoğunlaştırmaktır. XML, JSON veya uygulamanız tarafından okunabilen serileştirilmiş bir biçimde saklanabilir. Güncelleme işlemi de basit olacaktı. Etkinlik üzerine, yeni etkinliği bir sıraya yerleştirin (belki Amazon SQS veya başka bir şey kullanarak) ve ardından bir sonraki öğenin sırasını sürekli olarak yoklar. Bu öğeyi alın, ayrıştırın ve içeriğini veritabanında depolanan uygun besleme nesnesine yerleştirin.

Bu yöntemle ilgili iyi olan şey, belirli bir feed istendiğinde yalnızca bir dizi tabloyu okumak yerine tek bir veritabanı tablosunu okumanızdır. Ayrıca, listeyi her güncellediğinizde en eski etkinlik öğesini açabileceğiniz için sınırlı bir etkinlik listesi tutmanıza olanak tanır.

Bu yardımcı olur umarım! :)


Tam olarak düşüncelerim, muhtemelen şimdi aldığım düşüncelerimin doğrulanmasına ihtiyacım vardı, şerefe!
Sohail


3

Plurk'un yaklaşımının ilginç olduğunu düşünüyorum : tüm zaman çizelgenizi Google Finans'ın hisse senedi grafiklerine çok benzeyen bir biçimde sağlıyorlar.

Bir sosyal ağın nasıl çalıştığını görmek için Ning'e bakmaya değer olabilir . Geliştirici sayfaları özellikle yararlı görünüyor.


2

Bunu birkaç ay önce çözdüm, ancak uygulamamın çok basit olduğunu düşünüyorum.
Aşağıdaki modelleri oluşturdum:

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

Misal

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

2

Çeşitli uygulamalarda sosyal yayınlar, mikroblog ve işbirliği özelliklerini etkinleştirmek için etkinlik akışlarını uyguladıktan sonra, temel işlevselliğin oldukça yaygın olduğunu ve bir API aracılığıyla kullandığınız harici bir hizmete dönüştürülebileceğini fark ettim. Akışı bir üretim uygulamasına inşa ediyorsanız ve benzersiz veya derinden karmaşık ihtiyaçlarınız yoksa, kanıtlanmış bir hizmet kullanmak en iyi yol olabilir. Bunu, kendi basit çözümünüzü ilişkisel bir veritabanı üzerine yuvarlayarak üretim uygulamaları için kesinlikle tavsiye ederim.

Şirketim Collabinate ( http://www.collabinate.com ) bu gerçekleşmeden doğdu ve bunu elde etmek için bir grafik veritabanının üzerine ölçeklenebilir, yüksek performanslı bir etkinlik akışı motoru uyguladık. Aslında motoru oluşturmak için Graphity algoritmasının bir varyantını (burada da bir cevap veren @RenePickhardt'ın ilk çalışmalarından uyarlanmış) kullandık.

Motoru kendiniz barındırmak istiyorsanız veya özel işlevsellik istiyorsanız, çekirdek kodu aslında ticari olmayan amaçlar için açık kaynaktır, bu nedenle bir göz atabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.