चैटिंग इंटरफेस से कैसे बचें


10

पृष्ठभूमि: मैं एक सर्वर एप्लिकेशन डिज़ाइन कर रहा हूं और अलग-अलग सबसिस्टम के लिए अलग dll बना रहा हूं। चीजों को सरल बनाने के लिए, मान लें कि मेरे पास दो सबसिस्टम हैं: 1) Users2)Projects

उपयोगकर्ताओं के सार्वजनिक इंटरफ़ेस में एक विधि है:

IEnumerable<User> GetUser(int id);

और परियोजनाओं के सार्वजनिक इंटरफ़ेस की एक विधि है:

IEnumerable<User> GetProjectUsers(int projectId);

इसलिए, उदाहरण के लिए, जब हमें एक निश्चित परियोजना के लिए उपयोगकर्ताओं को प्रदर्शित करने की आवश्यकता होती है, तो हम कॉल कर सकते हैं GetProjectUsersऔर यह डेटाट्रेड्रिड या समान में दिखाने के लिए पर्याप्त जानकारी के साथ ऑब्जेक्ट वापस देगा।

समस्या: आदर्श रूप से, Projectsसबसिस्टम को उपयोगकर्ता की जानकारी को संग्रहीत नहीं करना चाहिए और इसे केवल एक परियोजना में भाग लेने वाले उपयोगकर्ताओं के Ids को संग्रहीत करना चाहिए। प्रस्तुत करने के लिए GetProjectUsers, इसे कहते हैं की जरूरत GetUserके Usersप्रत्येक उपयोगकर्ता आईडी अपने स्वयं के डेटाबेस में संग्रहीत के लिए प्रणाली। हालाँकि, इसके लिए अलग-अलग GetUserकॉल की बहुत आवश्यकता होती है , जिससे Userसबसिस्टम के अंदर अलग-अलग अलग-अलग sql क्वेरी होती हैं । मैंने वास्तव में इसका परीक्षण नहीं किया है लेकिन इस गंदी डिजाइन के होने से प्रणाली की स्थिरता प्रभावित होगी।

अगर मैं सबसिस्टम के पृथक्करण को अलग रख देता हूं, तो मैं सभी जानकारी को एक ही स्कीमा में स्टोर कर सकता हूं, जो दोनों प्रणालियों द्वारा सुलभ Projectsहो और JOINसभी प्रोजेक्ट उपयोगकर्ताओं को एक ही क्वेरी में प्राप्त करने के लिए कर सकता है । Projectsयह भी जानना होगा कि Userक्वेरी परिणामों से ऑब्जेक्ट कैसे उत्पन्न करें। लेकिन इससे अलगाव टूट जाता है जिसके कई फायदे हैं।

प्रश्न: क्या कोई व्यक्ति इन सभी व्यक्तिगत GetUserकॉल से बचने के दौरान अलगाव को बनाए रखने का एक तरीका सुझा सकता है GetProjectUsers?


उदाहरण के लिए, मुझे लगता है कि मेरे पास एक उपयोगकर्ता था जो बाहरी प्रणालियों को एक लेबल-मूल्य जोड़ी के साथ उपयोगकर्ताओं को "टैग" करने की क्षमता देता था, और उपयोगकर्ताओं को एक निश्चित मूल्य के साथ अनुरोध करने के लिए, जैसे:

void AddUserTag(int userId, string tag, string value);
IEnumerable<User> GetUsersByTag(string tag, string value);

तब प्रोजेक्ट सिस्टम प्रत्येक उपयोगकर्ता को टैग कर सकता है क्योंकि वे प्रोजेक्ट में जोड़े जाते हैं:

AddUserTag(userId,"project id", myProjectId.ToString());

और GetProjectUsers के दौरान, यह एक ही कॉल में सभी परियोजना उपयोगकर्ताओं से अनुरोध कर सकता है:

var projectUsers = usersService.GetUsersByTag("project id", myProjectId.ToString());

मैं इस बारे में निश्चित नहीं हूं: हां, उपयोगकर्ता परियोजनाओं के अज्ञेय हैं, लेकिन वास्तव में परियोजना सदस्यता के बारे में जानकारी उपयोगकर्ता प्रणाली में संग्रहीत की जाती है, परियोजनाएं नहीं। मुझे बस स्वाभाविक नहीं लगता है इसलिए मैं यह निर्धारित करने की कोशिश कर रहा हूं कि क्या यहां एक बड़ा नुकसान है जो मुझे याद आ रहा है।

जवाबों:


10

आपके सिस्टम में जो चीज गायब है वह कैश है।

तुम कहो:

हालाँकि, इसके लिए अलग-अलग GetUserकॉल की बहुत आवश्यकता होती है , जिससे Userसबसिस्टम के अंदर अलग-अलग अलग-अलग sql क्वेरी होती हैं ।

किसी विधि में कॉल की संख्या SQL क्वेरी की संख्या के समान नहीं होनी चाहिए। आपको एक बार उपयोगकर्ता के बारे में जानकारी मिल जाती है, यदि आप फिर से उसी जानकारी के लिए क्वेरी नहीं करेंगे तो यह क्यों नहीं बदली? बहुत संभव है, आप सभी उपयोगकर्ताओं को स्मृति में कैश भी कर सकते हैं, जिसके परिणामस्वरूप शून्य SQL प्रश्न (जब तक कि उपयोगकर्ता नहीं बदलता) नहीं होगा।

दूसरी ओर, Projectsसबसिस्टम क्वेरी को प्रोजेक्ट और उपयोगकर्ताओं दोनों के साथ बनाकर INNER JOIN, आप एक अतिरिक्त समस्या का परिचय देते हैं: आप अपने कोड में दो अलग-अलग स्थानों में सूचना के एक ही टुकड़े को क्वेरी कर रहे हैं, जिससे कैश अमान्यकरण बेहद मुश्किल हो जाता है। एक परिणाम के रूप में:

  • या तो आप किसी भी समय कैश का परिचय नहीं देंगे,

  • या जब आप जानकारी के एक टुकड़े को बदल देते हैं, तो अमान्य होने पर अध्ययन करने में सप्ताह या महीने खर्च होंगे,

  • या आप सीधे स्थानों पर कैश अमान्यता को जोड़ देंगे, दूसरे को भूल जाएंगे और परिणामस्वरूप बग ढूंढना मुश्किल होगा।


आपके प्रश्न का उत्तर देते हुए, मुझे लगता है कि मैंने पहली बार एक शब्द देखा: स्केलेबिलिटी । अंगूठे के एक नियम के रूप में, आप अगले पैटर्न का अनुसरण कर सकते हैं:

  1. अपने आप से पूछें कि क्या सिस्टम धीमा है (यानी यह प्रदर्शन की गैर-कार्यात्मक आवश्यकता का उल्लंघन करता है, या बस उपयोग करने के लिए एक बुरा सपना है)।

    यदि सिस्टम धीमा नहीं है , तो प्रदर्शन के बारे में परेशान न करें। साफ कोड, पठनीयता, स्थिरता, परीक्षण, शाखा कवरेज, स्वच्छ डिजाइन, विस्तृत और प्रलेखन, अच्छे कोड टिप्पणियों को समझने में आसान।

  2. यदि हाँ, तो अड़चन की खोज करें। आप ऐसा अनुमान लगाने से नहीं, बल्कि प्रोफाइलिंग से करते हैं । प्रोफाइलिंग करके, आप अड़चन का सटीक स्थान निर्धारित करते हैं (यह देखते हुए कि जब आप अनुमान लगाते हैं , तो आपको लगभग हर बार गलत हो सकता है), और अब कोड के उस हिस्से पर ध्यान केंद्रित कर सकते हैं।

  3. एक बार अड़चन पाए जाने पर समाधान खोजें। आप अनुमान लगाते हैं कि बेंचमार्किंग, प्रोफाइलिंग, विकल्प लिखना, कंपाइलर ऑप्टिमाइज़ेशन समझना, आपके ऊपर उठने वाले अनुकूलन को समझना, स्टैक ओवरफ्लो पर सवाल पूछना और निम्न-स्तरीय भाषाओं (असेंबलर सहित, आवश्यक होने पर) पर जाना।

Projectsसबसिस्टम के साथ वास्तविक मुद्दा क्या है जो सबसिस्टम के लिए जानकारी मांग रहा है Users?

अंतिम भविष्य मापनीयता मुद्दा? यह कोई मुद्दा नहीं है। स्केलेबिलिटी एक दुःस्वप्न बन सकती है यदि आप सब कुछ एक अखंड समाधान में विलय करना शुरू कर देते हैं या कई स्थानों से एक ही डेटा के लिए क्वेरी करते हैं (जैसा कि नीचे दिया गया है, क्योंकि कैश शुरू करने की कठिनाई के कारण)।

यदि पहले से ही ध्यान देने योग्य प्रदर्शन मुद्दा है, तो, चरण 2, अड़चन के लिए खोज करें।

यदि ऐसा प्रतीत होता है कि, वास्तव में, अड़चन मौजूद है और इस तथ्य के कारण है कि उपतंत्र के Projectsमाध्यम से उपयोगकर्ताओं के लिए अनुरोध Users(और डेटाबेस क्वेरी स्तर पर स्थित है), तो केवल आपको एक विकल्प की तलाश करनी चाहिए।

सबसे आम विकल्प कैशिंग को लागू करना होगा, जिससे प्रश्नों की संख्या में भारी कमी आएगी। यदि आप ऐसी स्थिति में हैं, जहाँ कैशिंग मदद नहीं करता है, तो आगे की रूपरेखा से यह पता चलता है कि आपको प्रश्नों की संख्या कम करने की आवश्यकता है, या डेटाबेस इंडेक्स को जोड़ना (या निकालना), या अधिक हार्डवेयर फेंकना, या पूरी प्रणाली को फिर से डिज़ाइन करना है। ।


जब तक मैं आपको गलत नहीं समझ रहा हूँ, आप कह रहे हैं "व्यक्तिगत गेटअप कॉल को रखें, लेकिन db राउंडटैप से बचने के लिए कैशिंग का उपयोग करें"।
एरेन एर्सोन्मेज़

@ ErenErsönmez: GetUserडेटाबेस को क्वेरी करने के बजाय, कैश में दिखेगा। इसका मतलब यह है कि यह वास्तव में मायने नहीं रखता है कि आप कितनी बार कॉल करेंगे GetUser, क्योंकि यह डेटाबेस के बजाय मेमोरी से डेटा लोड करेगा (जब तक कि कैश अमान्य नहीं किया गया है)।
आर्सेनी मूरज़ेंको

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

@ ErenErsönmez: आपके पास जितना अधिक डेटा है, उतना ही महत्वपूर्ण कैशिंग दिखाई देता है। अंगूठे के एक नियम के रूप में, रीड की संख्या को लिखने की संख्या से तुलना करें। यदि प्रति दिन "हजारों" दस्तावेज़ जोड़े जाते हैं और प्रति दिन लाखों selectक्वेरीज़ होती हैं, तो आप कैशिंग का बेहतर उपयोग करेंगे। दूसरी ओर, यदि आप किसी डेटाबेस में अरबों इकाइयाँ जोड़ रहे हैं, लेकिन selectबहुत ही चयनात्मक wheres के साथ केवल कुछ हजारों प्राप्त करते हैं , तो कैशिंग उतना उपयोगी नहीं हो सकता है।
आर्सेनी मोरज़ेंको

आप शायद सही हैं - मैं शायद एक समस्या को ठीक करने की कोशिश कर रहा हूं जो मेरे पास अभी तक नहीं है। मैं संभवत: लागू करूंगा और जरूरत पड़ने पर बाद में सुधार करने की कोशिश करूंगा। यदि कैशिंग उचित नहीं है, क्योंकि, संस्थाओं को जोड़े जाने के बाद केवल 1-2 बार पढ़ने की संभावना है, तो क्या आपको लगता है कि संभव है कि मैं इस प्रश्न से जुड़ा समाधान काम कर सकता हूं? क्या आप इसके साथ एक बड़ी समस्या देखते हैं?
एरेन एर्सोन्मेज़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.