सोशल नेटवर्क में गतिविधि स्ट्रीम को कैसे लागू किया जाए


140

मैं अपना खुद का सोशल नेटवर्क विकसित कर रहा हूं, और मुझे उपयोगकर्ताओं के कार्यों की धारा को लागू करने के वेब उदाहरणों पर नहीं मिला है ... उदाहरण के लिए, प्रत्येक उपयोगकर्ताओं के लिए कार्यों को कैसे फ़िल्टर किया जाए? कार्रवाई की घटनाओं को कैसे संग्रहीत करें? कौन सी डेटा मॉडल और ऑब्जेक्ट मॉडल मैं एक्शन स्ट्रीम के लिए और एक्शन सेल्फ के लिए उपयोग कर सकता हूं?


9
सौभाग्य, यह कभी न खत्म होने वाला प्रश्न है जिसे हम सभी जानना चाहते हैं, फेसबुक इसे कैसे खींचता है, इसका उत्तर बहुत जटिल है और हम इसे करने का सबसे कुशल तरीका कभी नहीं जान सकते हैं। यदि आपको एक अच्छा दृष्टिकोण मिलता है, तो कृपया इसे दूसरों के देखने के लिए यहां पोस्ट करें, बीटीडब्ल्यू को एसओ पर कई बार चर्चा की गई है, इसलिए बस खोज करें और आपको कुछ युक्तियां
मिलेंगी

1
स्ट्रीम फ्रेमवर्क सबसे व्यापक रूप से उपयोग किया जाने वाला समाधान है: github.com/tschellenbach/Stream-Framework इसके अलावा संकुल की इस सूची को देखें: djangopackages.com/grids/g/activities
Thierry

1
निजीकरण के संदर्भ में यह विश्लेषिकी और मशीन सीखने पर आधारित है, इसके अलावा getstream.io/personalization
थियरी

जवाबों:


241

सारांश : लगभग 1 मिलियन सक्रिय उपयोगकर्ताओं और 150 मिलियन संग्रहीत गतिविधियों के लिए, मैं इसे सरल रखता हूं:

  • अद्वितीय गतिविधियों के भंडारण के लिए एक रिलेशनल डेटाबेस का उपयोग करें (प्रति गतिविधि 1 रिकॉर्ड / "हुई बात") रिकॉर्ड्स को जितना हो सके उतना कॉम्पैक्ट बनाएं। संरचना ताकि आप जल्दी से गतिविधि आईडी या समय की कमी के साथ दोस्त आईडी के एक सेट का उपयोग करके गतिविधियों के एक बैच को पकड़ सकें।
  • जब भी कोई गतिविधि रिकॉर्ड बनाई जाती है, तो गतिविधि आईडी को रेडिस पर प्रकाशित करें, आईडी को एक "गतिविधि स्ट्रीम" सूची में प्रत्येक उपयोगकर्ता के लिए जो मित्र / ग्राहक है, जो गतिविधि को देखना चाहिए, को जोड़ रहा है।

किसी भी उपयोगकर्ता के लिए गतिविधि स्ट्रीम प्राप्त करने के लिए क्वेरी Redis और फिर आवश्यकतानुसार db से संबंधित डेटा को पकड़ो। यदि उपयोगकर्ता को समय में बहुत दूर ब्राउज़ करने की आवश्यकता है (यदि आप भी यह पेशकश करते हैं) तो db को क्वेरी करने के लिए वापस गिरें


मैं लगभग 15 मिलियन गतिविधियों से निपटने के लिए एक सादे पुराने MySQL तालिका का उपयोग करता हूं।

यह कुछ इस तरह दिखता है:

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_typeमुझे गतिविधि का प्रकार source_idबताता है , मुझे वह रिकॉर्ड बताता है जो गतिविधि से संबंधित है। इसलिए अगर गतिविधि प्रकार का अर्थ "जोड़ा पसंदीदा" है, तो मुझे पता है कि source_id एक पसंदीदा रिकॉर्ड की आईडी को संदर्भित करता है।

parent_id/parent_type मेरे ऐप के लिए उपयोगी होते हैं - वे मुझे बताओ कि गतिविधि से संबंधित है। यदि किसी पुस्तक का पक्ष लिया गया था, तो parent_id / parent_type मुझे बताएगा कि गतिविधि किसी दिए गए प्राथमिक कुंजी (आईडी) के साथ पुस्तक (प्रकार) से संबंधित है

मैं (user_id, time)उन गतिविधियों के लिए अनुक्रमित और क्वेरी करता हूं जो हैं user_id IN (...friends...) AND time > some-cutoff-point। आईडी को अलग करना और एक अलग क्लस्टर इंडेक्स का चयन करना एक अच्छा विचार हो सकता है - मैंने इसके साथ प्रयोग नहीं किया है।

सुंदर बुनियादी सामान, लेकिन यह काम करता है, यह सरल है, और आपकी आवश्यकताओं में बदलाव के साथ काम करना आसान है। इसके अलावा, यदि आप MySQL का उपयोग नहीं कर रहे हैं, तो आप बेहतर सूचकांक-वार करने में सक्षम हो सकते हैं।


सबसे हाल की गतिविधियों तक तेजी से पहुंचने के लिए, मैं रेडिस के साथ प्रयोग कर रहा हूं । Redis अपने सभी डेटा इन-मेमोरी को स्टोर करता है, इसलिए आप अपनी सभी गतिविधियों को वहां नहीं रख सकते हैं, लेकिन आप अपनी साइट पर अधिकांश हिट स्क्रीन के लिए पर्याप्त स्टोर कर सकते हैं। प्रत्येक उपयोगकर्ता के लिए सबसे हाल ही में 100 या ऐसा कुछ। मिश्रण में रेडिस के साथ, यह इस तरह काम कर सकता है:

  • अपना MySQL गतिविधि रिकॉर्ड बनाएं
  • गतिविधि बनाने वाले उपयोगकर्ता के प्रत्येक मित्र के लिए, Redis में उनकी गतिविधि सूची में ID पुश करें।
  • प्रत्येक सूची को अंतिम X आइटम पर ट्रिम करें

रेडिस तेज़ है और एक कनेक्शन में पाइपलाइन कमांड का एक तरीका प्रदान करता है - इसलिए 1000 दोस्तों को एक गतिविधि को धकेलने में मिलीसेकंड लगता है।

मैं जिस बारे में बात कर रहा हूं, उसके अधिक विस्तृत विवरण के लिए, रेडिस का ट्विटर उदाहरण देखें: http://redis.io/topics/twitter-one

फरवरी 2011 को अपडेट करें मुझे इस समय 50 मिलियन सक्रिय गतिविधियां मिली हैं और मैंने कुछ भी नहीं बदला है। इसके समान कुछ करने के बारे में एक अच्छी बात यह है कि यह कॉम्पैक्ट, छोटी पंक्तियों का उपयोग करता है। मैं कुछ बदलाव करने की योजना बना रहा हूं, जिसमें उन गतिविधियों के कई और कार्य और अधिक प्रश्न शामिल होंगे और मैं निश्चित रूप से चीजों को तेजी से रखने के लिए रेडिस का उपयोग करूंगा। मैं अन्य क्षेत्रों में रेडिस का उपयोग कर रहा हूं और यह वास्तव में कुछ प्रकार की समस्याओं के लिए अच्छी तरह से काम करता है।

जुलाई 2014 को अपडेट करें हम लगभग 700K मासिक सक्रिय उपयोगकर्ता हैं। पिछले कुछ वर्षों से, मैं प्रत्येक उपयोगकर्ता के लिए अंतिम 1000 गतिविधि आईडी के भंडारण के लिए रेडिस (जैसा कि बुलेटेड सूची में वर्णित है) का उपयोग कर रहा हूं। आमतौर पर सिस्टम में लगभग 100 मिलियन गतिविधि रिकॉर्ड होते हैं और वे अभी भी MySQL में संग्रहीत हैं और अभी भी वही लेआउट हैं। ये रिकॉर्ड हमें कम रेडिस मेमोरी के साथ दूर जाने देते हैं, वे गतिविधि डेटा के रिकॉर्ड के रूप में काम करते हैं, और अगर उपयोगकर्ता कुछ खोजने के लिए समय में आगे पृष्ठ की आवश्यकता होती है तो हम उनका उपयोग करते हैं।

यह एक चतुर या विशेष रूप से दिलचस्प समाधान नहीं था, लेकिन इसने मुझे अच्छी तरह से सेवा दी है।


2
रेडिस के लिए +1। v2 वर्चुअल मेमोरी का उपयोग करता है इसलिए
रेडिस

16
यदि गतिविधि (जोड़ें, टिप्पणी, जैसे, आदि) के कई स्रोत हैं, तो आप वास्तविक गतिविधियों के साथ इस तालिका में कैसे शामिल होते हैं? क्या आप कई लेफ्ट जॉइन का उपयोग करते हैं (प्रत्येक गतिविधि तालिका के लिए)?
अली शाकिबा

1
@casey गूंज @JohnS 'सवाल - आप JOINविभिन्न activity_typeतालिकाओं पर कैसे प्रदर्शन करते हैं ? क्या वे महंगी प्रदर्शन-वार में शामिल होते हैं?
रोब सोबर्स

1
क्या किसी को "जॉइन" के बारे में जॉनएस के सवाल का जवाब मिला है। क्या कोई ऐसा लिंक पोस्ट कर सकता है जहाँ उसे समझाया जा सके? मुझे भी ऐसा ही करना है और यह मेरे लिए बहुत मददगार होगा।
वसीम

3
कोई जुड़ता नहीं। एक अद्वितीय प्रति क्वेरी activity_typeजो आपको आवश्यक अन्य डेटा प्राप्त करने के लिए है।
निकली

21

यह mysql का उपयोग करते हुए एक गतिविधि स्ट्रीम का मेरा कार्यान्वयन है। तीन वर्ग हैं: गतिविधि, एक्टिविटी फ़ेड, सब्सक्राइबर।

गतिविधि एक गतिविधि प्रविष्टि का प्रतिनिधित्व करती है, और इसकी तालिका इस तरह दिखती है:

id
subject_id
object_id
type
verb
data
time

Subject_idकार्रवाई करने वाली वस्तु object_idकी आईडी है, कार्रवाई प्राप्त करने वाली वस्तु की आईडी। typeऔर verbस्वयं ही कार्रवाई का वर्णन करता है (उदाहरण के लिए, यदि उपयोगकर्ता किसी लेख में एक टिप्पणी जोड़ते हैं, तो वे "टिप्पणी" और "क्रमशः" बनाई जाएगी), डेटा में अतिरिक्त डेटा शामिल होता है ताकि जोड़ से बचा जा सके (उदाहरण के लिए, इसमें विषय नाम हो सकता है और उपनाम, लेख का शीर्षक और यूआरएल, टिप्पणी निकाय आदि)।

प्रत्येक गतिविधि एक या अधिक गतिविधिफ़ीड्स से संबंधित है, और वे एक तालिका से संबंधित हैं जो इस तरह दिखता है:

feed_name
activity_id

मेरे आवेदन में मेरे पास प्रत्येक उपयोगकर्ता के लिए एक फीड है और प्रत्येक आइटम (आमतौर पर ब्लॉग लेख) के लिए एक फीड है, लेकिन वे जो चाहें कर सकते हैं।

एक सब्सक्राइबर आमतौर पर आपकी साइट का एक उपयोगकर्ता होता है, लेकिन यह आपके ऑब्जेक्ट मॉडल में कोई भी वस्तु भी हो सकता है (उदाहरण के लिए एक लेख को उसके निर्माता के feed_action के लिए सदस्यता लिया जा सकता है)।

प्रत्येक सब्सक्राइबर एक या अधिक एक्टिविटीफीड्स से संबंधित है, और, ऊपर की तरह, वे इस तरह के लिंक टेबल से संबंधित हैं:

feed_name
subscriber_id
reason

यहां reasonफ़ील्ड बताता है कि ग्राहक ने फ़ीड क्यों सदस्यता ली है। उदाहरण के लिए, यदि कोई उपयोगकर्ता किसी ब्लॉग पोस्ट को बुकमार्क करता है, तो इसका कारण 'बुकमार्क' है। यह मुझे बाद में उपयोगकर्ताओं के लिए सूचनाओं को फ़िल्टर करने की क्रियाओं में मदद करता है।

एक ग्राहक के लिए गतिविधि को पुनः प्राप्त करने के लिए, मैं तीन तालिकाओं का एक सरल जुड़ाव करता हूं। यह जुड़ाव तेज़ है क्योंकि मैं ऐसी WHEREस्थिति के लिए कुछ गतिविधियों का चयन करता हूं जो अब जैसी दिखती हैं - time > some hours। मैं गतिविधि तालिका में डेटा क्षेत्र के लिए अन्य जॉइन धन्यवाद से बचता हूं।

reasonक्षेत्र पर आगे की व्याख्या । यदि, उदाहरण के लिए, मैं उपयोगकर्ता को ईमेल सूचनाओं के लिए क्रियाओं को फ़िल्टर करना चाहता हूं, और उपयोगकर्ता ने एक ब्लॉग पोस्ट को बुकमार्क किया है (और इसलिए वह 'बुकमार्क' के कारण पोस्ट फीड की सदस्यता लेता है), मैं नहीं चाहता कि उपयोगकर्ता प्राप्त करे उस आइटम पर होने वाली कार्रवाइयों के बारे में ईमेल सूचनाएँ, जबकि अगर वह पोस्ट पर टिप्पणी करता है (और इसलिए यह कारण 'टिप्पणी' के साथ पोस्ट फ़ीड की सदस्यता लेता है) मैं चाहता हूं कि जब अन्य उपयोगकर्ता उसी पोस्ट पर टिप्पणी जोड़ते हैं तो उन्हें सूचित किया जाए। कारण क्षेत्र मुझे इस भेदभाव में मदद करता है (मैंने इसे एक एक्टिविटीफिल्टर क्लास के माध्यम से लागू किया है), साथ में उपयोगकर्ता की सूचनाओं की प्राथमिकताएँ भी।


निकोलो मार्टिनी मैं गतिविधि पर उत्तर टिप्पणी जोड़ना चाहता था और इसे इसके तहत दिखाता था, यह आपकी संरचना के साथ कैसे संभव है? क्या मुझे एक और तालिका जोड़नी चाहिए या बस उसी का उपयोग करना चाहिए, यदि वही है, तो आपके सुझाव क्या हैं?
Basit

इस कार्यान्वयन का प्रदर्शन कैसा है? बड़े टेबलों पर कोई परीक्षण?
जोशुआ एफ। रौनट्री

16

गतिविधि स्ट्रीम के लिए एक वर्तमान प्रारूप है जिसे अच्छी तरह से जानने वाले लोगों के झुंड द्वारा विकसित किया जा रहा है।

http://activitystrea.ms/

मूल रूप से, प्रत्येक गतिविधि में एक अभिनेता होता है (जो गतिविधि करता है), एक क्रिया (गतिविधि की क्रिया), एक वस्तु (जिस पर अभिनेता प्रदर्शन करता है), और एक लक्ष्य।

उदाहरण के लिए: मैक्स ने एडम की दीवार के लिए एक लिंक पोस्ट किया है।

लेखन के समय उनका JSON का संस्करण 1.0 संस्करण पर पहुंच गया है, जो उस गतिविधि के लिए पैटर्न दिखाता है जिसे आप लागू कर सकते हैं।

उनके प्रारूप को पहले ही बीबीसी, ग्निप, गूगल बज़ गोवला, आईबीएम, माइस्पेस, ओपेरा, सोशलकास्ट, सुपरफूड, टाइपपैड, विंडोज लाइव, वाईआईआईडी और कई अन्य लोगों द्वारा अपनाया गया है।


hi @sntran मुझे पता है कि यह पोस्ट वर्षों पहले थी, लेकिन मेरे पास गतिविधि स्ट्रीम के बारे में अधिक प्रश्न हैं। क्या कोई तरीका है जिससे आप मदद कर सकते हैं?

ज़रूर। क्या पूछते हैं?
सून ट्रन-न्ग्यूएन

मेरा प्रश्न वास्तव में यहाँ पोस्ट किया गया है! लिंक । मुझे लगता है कि मुझे गतिविधि स्ट्रीम की एक बुनियादी समझ है, लेकिन मैं वास्तव में इसे लागू करने के तरीके के बारे में निश्चित नहीं हूं (यानी क्या मुझे कोणीय या नोड.जेएस का उपयोग करना चाहिए?) और वहां से, मैं वास्तव में एक गतिविधि स्ट्रीम कैसे बना सकता हूं? आने वाली एपीआई JSON? ये ऐसे मूल प्रश्न हैं, लेकिन मुझे ऑनलाइन कोई उत्तर नहीं मिला। यदि आप मदद कर सकते हैं, तो मैं वास्तव में इसकी सराहना करूंगा। धन्यवाद!
उनकी जूली

13

मुझे लगता है कि बड़ी वेबसाइटों पर सूचना प्रणाली कैसे काम करती है, इस पर एक स्पष्टीकरण स्टैक ओवरफ्लो प्रश्न में पाया जा सकता है कि सोशल नेटवर्किंग वेबसाइट दोस्तों के अपडेट की गणना कैसे करती है? , जेरेमी वॉल के जवाब में। वह संदेश क्यूई के उपयोग का सुझाव देता है और वह दो खुले स्रोत वाले सॉफ्टवेयर्स को इंगित करता है जो इसे लागू करते हैं:

  1. RabbitMQ
  2. अपाचे QPid

यह भी देखें कि सामाजिक गतिविधि धारा को लागू करने का सबसे अच्छा तरीका क्या है?


1

आपको एक प्रदर्शनकर्ता और वितरित संदेश कतार की आवश्यकता है। लेकिन यह वहाँ समाप्त नहीं होता है, आपको लगातार डेटा के रूप में क्या स्टोर करना है और क्या क्षणिक और आदि के रूप में निर्णय लेना होगा।

वैसे भी, यदि आप उच्च प्रदर्शन और स्केलेबल सिस्टम के बाद हैं, तो यह वास्तव में एक मुश्किल काम है। लेकिन, निश्चित रूप से कुछ उदार इंजीनियरों ने इस पर अपना अनुभव साझा किया है। लिंक्डइन ने हाल ही में अपना संदेश कतार प्रणाली कफका खुला स्रोत बनाया। इससे पहले, फेसबुक ने पहले ही ओपन सोर्स समुदाय को Scribe प्रदान किया था। काफ्का को स्काला में लिखा गया है और सबसे पहले इसे चलाने में कुछ समय लगता है लेकिन मैंने कुछ वर्चुअल सर्वर के साथ परीक्षण किया। यह वास्तव में तेज है।

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

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


0

अपने स्वयं के रोल करने के बजाय, आप एक एपीआई के माध्यम से उपयोग की जाने वाली तीसरी पार्टी सेवा को देख सकते हैं। मैंने कोलाबनेट ( http://www.collabinate.com ) नामक एक शुरुआत की जिसमें एक ग्राफ डेटाबेस बैकएंड है और अत्यधिक समवर्ती, उच्च प्रदर्शन तरीके से बड़ी मात्रा में डेटा को संभालने के लिए कुछ काफी परिष्कृत एल्गोरिदम हैं। हालांकि इसमें कार्यक्षमता की चौड़ाई नहीं है जो फेसबुक या ट्विटर करते हैं, यह अधिकांश उपयोग के मामलों के लिए पर्याप्त से अधिक है, जहां आपको किसी एप्लिकेशन में गतिविधि स्ट्रीम, सामाजिक फ़ीड या माइक्रोब्लॉगिंग कार्यक्षमता बनाने की आवश्यकता होती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.