Mostafa Ali Mansour
Mostafa Ali Mansour

@MostafaAliManos

34 تغريدة 58 قراءة Jun 24, 2021
يلا بينا نعمل الSystem design بتاع تويتر و ولا الحوجة لعم جاك و نحط هاشتاج #SaveSheikhJarrah براحتنا.
البداية زي ما اتفقنا نحدد الRequirements .. حنقسمها ل Functional و Non-Functional
Function Requirements
بتبقى عبارة عن الFeatures اللي الapplication المفروض ي supportها .. ف حالة تويتر (نعمل لايك .. نعمل فولو .. أديكي سيجارة تديني سيجارة أولعلك تطفيها تجولي هوف)
الNon-functional requirements هي الحاجات اللي بتخص الPerformance بتاع الapplication من حيث الavailability و الlatency و هكذا
Functional requirements
١- اليوزر يتويت و يصيح براحته
٢- اليوزر يعمل فولو ليوزرز تانيين
٣- نقدر نعمل لايكات لبعض
٤- نقدر نتويت ب صور و فيديوهات
٥- نقدر نشوف تويتات الناس
Non-functional
١- الأبليكاشن يبقى available عشان مش كل شوية نقول تويتر واقع تعالى واتس.
٢- الlatency متبقاش عالية من لما الtweet تتكتب لحد ما تتقرا
٣- ممكن نفضل الavailability عن الconsistency بمعنى لو حضرتك دخلت عندي ف البروفايل وانا عملت تويت .. مش حتشوفها غير لما تعمل ريفريش
مش لازم تشوف الdata in real time عشان هي مش حاجة critical زي مثلا applications الFinTech .. ف قشطة ممكن تتأخر عنك حبة في مقابل ان تويتر مقفلش ف وشك.
يلا بينا نestimate ؟
احنا بالصلاة عالنبي حيبقى عندنا بليون مستخدم .. نقول ٢٠٠ منهم DAU: Daily Active Users
كل واحد من دول بيعمل لايك على ٥ تويتات ف اليوم
و بيفتح بروفايل البيست فريند و بروفايل الكراش يعني بروفايلين ف اليوم
و كل بروفايل بيكتب ٢٠ تويتة ف اليوم
حاجة ظريفة انك تبتدي الestimations ب user story بسيطة من الrequirement.
كده
200M users* ((2 profiles+5 tweets) * 20 tweets) = 280 Billion read operations/day
و 200M users * 20 = 4 billion write operations/day
كده عرفنا ان السيستم read heavy و ده
حيساعدنا قدام اننا نحدد انهي Database technology تقدر تزق معانا.
فل .. تعالى دلوقتي نشوف الstorage بتاع صياحنا:
التويتة فيها 280 character .. و ال UTF-8 character = 1 byte بس الUTF-8 Char الصيني بياخد 3 و فيه لغات بتاخد 2 .. ف نخلينا ف 3 bytes أضمن لينا
طيب كده التويتة الواحدة حتاخد 280*3 = 840 bytes نخليها 1kilobyte تسهيلًا علينا
و للتويتة ليها metadata زي الuserId و الtweetId و الlocation ف نقول شاكب راكب دول يعملوا 30 bytes
بما اننا حان support الصور و الفيديوهات عشان الميمز .. محتاجين نعمل حسابهم
الموبايلات الجديدة بقت تصور بquality حلوة ف نقول الصورة تعمل 2Megabyte average و الفيديوهات تعمل 10Megabytes
نفترض ان 10% من التويتات حتحتوي على صور و 5% حيبقوا فيديوهات .. و كل تويتة حيبقى فيها characters
و احنا قلنا اننا ف اليوم حيبقى عندنا
4 billion tweets
Text only tweet = 4b * 1.3M = 5.5 peta bytes
ناخد ١٠٪ منهم عشان الصور
55 tera bytes
و ال٥٪ عشان الفديوهات
27.5 terabytes
و نجمع كله مع بعضه =
5582.5 terabyte
نخليها 5.6 petabytes ..
5.6 petabytes per day .. wow
عرفنا حنخزن قد ايه .. فاضل الbandwidth و ده ساهل .. نقسم الرقم على عدد الثواني ف اليوم = 5.6/86400 يعني بالتقريب 64 terabyte/second
اللي جي محتاجين نحدد الAPI shape .. حنبتدي بالPublic endpoints اللي هي متاحة لليوزر
tweet(api_dev_key, user_id, tweet_id, location_x, location_y, photo_id, video_id)
الصورة و الفيديو و اللوكاشين optional و الuser_id و الtweet_id مفهومين .. api_dev_key ده عبارة عن key تويتر بيعمله generate per user و بيبقى ليه quota معينة
الغرض منه ان يبقى فيه quota محددة لليوزر يتويت فيها .. غير كده ممكن يشك انه bot.
نيجي لل High level design
ربنا مباركلنا و عندنا users بالعبيط .. محتاجين كذا Application Server يخدم عليهم .. و load balancer عشان يbalance الload
#حمادةـهلال
بالنسبة للdata ف احنا ممكن يبقى عندنا نوعين
نوع عادي عشان يخزن الtextual data زي الuser_Id و الtweet
و التاني File System storage أو Object storage زي S3 بتاع AWS
الschema بتاعة الdatabase و حجم الdata هما اللي بيحددوا نوع الdatabase اللي حنستعملها .. عندنا نعين
SQL: بتستعمل لما يبقى فيه
كتيرة relationships و محتاجين consistency و بتبقى بالشكل التقليدي بتاع الrows and columns
NoSQL: The value is JSON or un-uniform in general
عيب الSQL انه مينفعش ي scale بسهولة لما الداتا تبقى كبيرة .. و عيب ال NoSQL ان لما الداتا تبقى coupled ال query بيبقى مكلف و أصعب.
الschema: عندنا User tables و ده فيه الUser_Id, email, date of birth
UserFollows table ده فيه جدول الناس اللي اليوزر بيتابعهم
Tweet table: tweet_Id, time_stamp, location_x, location_y, media_Id, number_of_likes
Likes table: tweet_Id, user_id, time_stamp
الحقيقة ان الdata هنا مترابطة قوي .. ال SQL حتساعدنا أكتر .. لو اختارنا NoSQL حنحتاج table يحدد الrelationship ما بين الuser و الuser followers
هنا بنبتدي نشوف الtradeoffs بين الSQL و الNoSQL .. مفيش system design صح .. فيه design حلو و design متعب و مش حاي scale
الحاجة الحلوة ف الNoSQL انه حايساعد ف الread heavy operations أحسن من الSQL عشان الblock size حتبقى أصغر بدل ما يدور ف row بحاله + ممكن
ف الtable بتاع التويت نعمل ف الJSON الmetadata بطريقة نظيفة + حا scale معانا ب أريحية.
ممكن نستعمل Database زي Casandra .. هي بتقدم reliability solution و بت create replicas من نفسها عشان منقلقش لو حاجة حصلت للprimary database
برضه مش عايزين ان الconnections تبقى كلها مليانة بupload requests سواء صور أو فيديوهات و يحصل bottleneck للسيرفر .. ف نقسم 2 services واحدة للread و واحدة للwrite و نحدد الbandwidth بناءًا على الback of the envelope calculations اللي عملناها فوق
زائد ان ده حايساعد ف الdata analysis نشوف حتى عدد الusers اللي بيupload صور و فيديوهات و أماكنهم .. بدل ما ن separate on the application layer
Losing files is not an option for our service.
دايما يبقى فيها replicas للdatabase و يبقى فيه instances لل server جاهزة يت fallback عليها عشان الusers ميحسوش بحاجة
اوعى يا واض يا رضا الservice متبقاش available
احنا قلنا عندنا data بالعبيط .. طبعًا مش حيتخزنوا ف database واحدة .. بنعمل Sharding .. يعني بيقى عندنا كذا database server .. و جوة الphysical servers دول فيه logical database servers بي reference عالداتا.
ممكن نعمل shard على الUser_Id و نحط صور الuser ف نفس الshard .. و لنفرض ان عدد الshards حيبقوا 10 .. ف لما يبقى فيه user جديد نعمل user_id %10 و نرميه ف الshard و نخلص.
و بالنسبة لل photo_id .. ن generate الid بإننا نخلي لكل shard auto increment و لما نيجي نحط صورة
نعمل append للincrement مع الshard Id عشان يبقى unique
طبعا الاقتراح ده مصيبة سودة و زي الزفت .. قوتلتلي ليه
١- لو الshard وقع .. كده حنخسر user و photo
٢- فيه users بيحطوا صور كتير و ناس بتحط صورة البيضة
٣- فيه hot user (اوه ياه) بيبقى ليها followers كتير
فولورز كتير يعني read operations كتير يعني الshard حيبقى overloaded
٤- ايش عرفك ان الshard حيكفي كل صور اليوزر
الأحسن .. ن shard على حسب الphoto_id .. و كده كده حنعرف نجيب الصورة دي بتاعة مين .. معندناش حاجة بتضيع هنا .. طيب حان generate الphoto id ازاي ؟
ممكن يبقى عندنا database بت auto increment the photo_id و ناخدها نرميها عالشارد .. بس طبعًا حنحتاج replica ليها و تفضل مصحصها هي وقفت لحد رقم كام عشان لو وقعت تاخد مكانها و متبقاش single point of failure
او ممكن يبقى عندنا 2 databases واحدة تgenerate even numbers و التانية تعمل الodd الأشرار
لو ربنا فتحها علينا و بقى عندنا users أكتر .. ممكن ن migrate الlogical shards ل new physical shards .. بيبقى فيه config file مقسم الrange .. كل range يتحط ف انهي shard .. اسمه Zookeeper
الحقيقة حنخلي حتة الnews feed ف ثريد تاني .. بس فاضل كده نحط CDN عشان ي cache الداتا و نستعمل Memcache عشان ي cache الhot tweet مثلا Least Recently Used (LRU) ممكن تبقى caching policy مناسبة بما اننا مش عايزين ن cache تويتات قديمة
و بس يا حبايبي .. عملنا طويطر قمر زيكوا و أتمنى انكوا تكونوا استمتعتوا معانا النهاردة 😘❤️
نسيت أقول ان الdiagrams متاخدة من educative.io
لسه واخد بالي .. المفروض ن shard عالtweet_id مش الphoto_id 🤦🏻‍♂️

جاري تحميل الاقتراحات...