कैसे कुंजी आधारित कैशिंग काम करता है?


10

मैंने हाल ही में 37Signals ब्लॉग पर एक लेख पढ़ा और मुझे आश्चर्य हो रहा है कि यह कैसे होता है कि वे कैश कुंजी प्राप्त करते हैं।

यह सब अच्छी तरह से और अच्छा है कैश कुंजी है जिसमें ऑब्जेक्ट का टाइमस्टैम्प शामिल है (इसका मतलब है कि जब आप ऑब्जेक्ट को अपडेट करते हैं तो कैश अमान्य हो जाएगा); लेकिन आप तब कैसे कैश कुंजी का उपयोग टेम्पलेट में बिना किसी डीबी हिट के कारण करते हैं जो आप कैश से लाने की कोशिश कर रहे हैं।

विशेष रूप से, यह एक से कई संबंधों को कैसे प्रभावित करता है जहां आप उदाहरण के लिए पोस्ट की टिप्पणियाँ दे रहे हैं।

Django में उदाहरण:

{% for comment in post.comments.all %}
   {% cache comment.pk comment.modified %}
     <p>{{ post.body }}</p>
   {% endcache %}
{% endfor %}

उदाहरणों के लिए केवल अनुरोध करने के लिए रेल में कैशिंग अलग है (मुझे पता है कि वे आपकी कैश कुंजी को कुछ अलग में बदल देते हैं)। क्या वे भी कैश को कैश करते हैं?


एक Django उदाहरण के लिए rossp.org/blog/2012/feb/29/fragment-caching पर एक नज़र डालें !
vdboor

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

यह सच है, यह भी 37signals कोड के साथ होता है, यह रेंडरिंग कोड पर फोकस्ड है। चाल पूरी सूची को किसी अन्य कंटेनर में भी कैश करने के लिए है, या ऑब्जेक्ट की पुनर्प्राप्ति को कहीं और कैश करना है।
vdboor

वास्तव में उनकी कैचिंग रणनीति थोड़ी अधिक शिक्षित है। मैं इस लेख को भी
सुझाता हूं

ऐसा लगता है कि आपके कोड स्निपेट में एक टाइपो है - करने का post.bodyइरादा था comment.body?
इजाकाता

जवाबों:


3

एक पहले से लोड की गई वस्तु के सीधे डंप को कैशिंग करने के लिए, हाँ, आप कुछ भी नहीं या अगले-कुछ भी नहीं हासिल करते हैं। यही नहीं उन उदाहरणों का वर्णन किया जा रहा है - वे एक पदानुक्रम का वर्णन कर रहे हैं, जहां कुछ कम करने के लिए किसी भी परिवर्तन को भी पदानुक्रम में उच्चतर सब कुछ के लिए एक अद्यतन ट्रिगर करना चाहिए।

37signals ब्लॉग से पहला उदाहरण, Project -> Todolist -> Todoपदानुक्रम के रूप में उपयोग करता है। एक आबाद उदाहरण इस तरह दिख सकता है:

Project: Foo (last_modified: 2014-05-10)
   Todolist:  Bar1 (last_modified: 2014-05-10)
       Todo:  Bang1 (last_modified: 2014-05-09)
       Todo:  Bang2 (last_modified: 2014-05-09)

   Todolist:  Bar2 (last_modified: 2014-04-01)
       Todo:  Bang3 (last_modified: 2014-04-01)
       Todo:  Bang4 (last_modified: 2014-04-01)

तो, चलिए Bang3अपडेट किया गया था। इसके सभी अभिभावक भी अपडेट रहें:

Project: Foo (last_modified: 2014-05-16)
   Todolist:  Bar2 (last_modified: 2014-05-16)
       Todo:  Bang3 (last_modified: 2014-05-16)

फिर जब रेंडर करने का समय आता है, Projectतो डेटाबेस से लोड करना मूल रूप से अपरिहार्य है। आपको शुरू करने के लिए एक बिंदु की आवश्यकता है। हालाँकि, क्योंकि यह अपने सभी बच्चोंlast_modified का एक संकेतक है , यही कारण है कि आप बच्चों को लोड करने के प्रयास से पहले कैश कुंजी के रूप में उपयोग करते हैं।


जबकि ब्लॉग पोस्ट अलग टेम्प्लेट का उपयोग करते हैं, मैं उन्हें एक में एक साथ गांठ करने वाला हूं। उम्मीद है कि एक ही स्थान पर पूरी बातचीत देखने से यह थोड़ा स्पष्ट हो जाएगा।

तो, Django टेम्पलेट कुछ इस तरह दिख सकता है:

{% cache 9999 project project.cache_key %}
<h2>{{ project.name }}<h2>
<div>
   {% for list in project.todolist.all %}
   {% cache 9999 todolist list.cache_key %}
      <ul>
         {% for todo in list.todos.all %}
            <li>{{ todo.body }}</li>
         {% endfor %}
      </ul>
   {% endcache %}
   {% endfor %}
</div>
{% endcache %}

कहते हैं कि हम एक ऐसी परियोजना से गुजरते हैं, जो cache_keyअभी भी कैश में मौजूद है। क्योंकि हम माता-पिता से संबंधित सभी वस्तुओं में परिवर्तन का प्रचार करते हैं, यह तथ्य कि विशेष कुंजी अभी भी मौजूद है मतलब है कि संपूर्ण प्रदान की गई सामग्री को कैश से खींचा जा सकता है।

यदि वह विशेष प्रोजेक्ट अभी-अभी अपडेट किया गया है - उदाहरण के लिए, जैसा कि Fooऊपर दिया गया है - तो उसे अपने बच्चों को प्रस्तुत करना होगा, और उसके बाद ही वह उस प्रोजेक्ट के लिए सभी टॉडोलिस्ट के लिए क्वेरी चलाएगा। इसी तरह एक विशिष्ट टोडोलिस्ट के लिए - यदि उस सूची का cache_key मौजूद है, तो उसके अंदर के टॉडोस नहीं बदले हैं, और पूरी चीज को कैश से खींचा जा सकता है।

यह भी ध्यान दें कि मैं todo.cache_keyइस टेम्पलेट का उपयोग कैसे नहीं कर रहा हूं । यह इसके लायक नहीं है, जैसा कि आप सवाल में कहते हैं, bodyडेटाबेस से पहले ही खींच लिया गया है। हालाँकि, डेटाबेस हिट एकमात्र कारण नहीं है जिससे आप कुछ कैश कर सकते हैं। उदाहरण के लिए, कच्चे मार्कअप टेक्स्ट (जैसे कि हम StackExchange पर प्रश्न / उत्तर बॉक्स में क्या टाइप करते हैं) और इसे HTML में कनवर्ट करने में पर्याप्त समय लग सकता है जिससे परिणाम को कैशिंग करना अधिक कुशल होगा।

यदि ऐसा था, तो टेम्प्लेट में आंतरिक लूप इस तरह दिख सकता है:

         {% for todo in list.todos.all %}
            {% cache 9999 todo todo.cache_key %}
               <li>{{ todo.body|expensive_markup_parser }}</li>
            {% endcache %}
         {% endfor %}

तो सब कुछ एक साथ खींचने के लिए, आइए इस उत्तर के शीर्ष पर अपने मूल डेटा पर वापस जाएं। यदि हम मान लें:

  • सभी वस्तुओं को उनके मूल राज्य में कैश किया गया था
  • Bang3 बस अद्यतन किया गया था
  • हम संशोधित टेम्पलेट प्रदान कर रहे हैं (सहित expensive_markup_parser)

फिर यह है कि सब कुछ कैसे लोड किया जाएगा:

  • Foo डेटाबेस से पुनर्प्राप्त किया जाता है
  • Foo.cache_key (2014-05-16) कैश में मौजूद नहीं है
  • Foo.todolists.all()क्वियर है: Bar1और Bar2डेटाबेस से पुनर्प्राप्त किया जाता है
  • Bar1.cache_key(2014-05-10) कैश में पहले से मौजूद है ; इसे पुनः प्राप्त और आउटपुट करें
  • Bar2.cache_key (2014-05-16) कैश में मौजूद नहीं है
  • Bar2.todos.all()क्वियर है: Bang3और Bang4डेटाबेस से पुनर्प्राप्त किया जाता है
  • Bang3.cache_key (2014-05-16) कैश में मौजूद नहीं है
  • {{ Bang3.body|expensive_markup_parser }} प्रस्तुत है
  • Bang4.cache_key(2014-04-01) पहले से ही कैश में मौजूद है ; इसे पुनः प्राप्त और आउटपुट करें

इस छोटे उदाहरण में कैश से बचत हैं:

  • डेटाबेस हिट से बचा गया: Bar1.todos.all()
  • expensive_markup_parserबचा 3 बार: Bang1, Bang2, औरBang4

और निश्चित रूप से, अगली बार जब यह देखा Foo.cache_keyजाएगा, तो मिल जाएगा, इसलिए प्रदान करने की एकमात्र लागत Fooडेटाबेस से अकेले पुनर्प्राप्त कर रही है और कैश क्वेरी कर रही है।


-2

आपका उदाहरण अच्छा है अगर उसे प्रत्येक टिप्पणी के लिए कुछ डेटा पुनर्प्राप्ति या प्रसंस्करण की आवश्यकता है। यदि आप केवल शरीर लेते हैं और इसे प्रदर्शित करते हैं - तो कैश बेकार हो जाएगा। लेकिन आप सभी टिप्पणियों ट्री ({% के ​​लिए% सहित) को कैश कर सकते हैं। इस मामले में आपको इसे हर जोड़ा टिप्पणी के साथ अमान्य करने की आवश्यकता है, इसलिए आप पिछली टिप्पणी टाइमस्टैम्प या टिप्पणियों को पोस्ट में कहीं भी रख सकते हैं और इसके साथ टिप्पणी कैश कुंजी बना सकते हैं। यदि आप अधिक सामान्यीकृत डेटा पसंद करते हैं, और केवल एक पृष्ठ पर टिप्पणियों का उपयोग करते हैं, तो आप टिप्पणी सहेजें पर केवल एक कैश कुंजी साफ़ कर सकते हैं।

मेरे लिए, पोस्ट में टिप्पणियां सहेजना काफी अच्छा लगता है (यदि आप टिप्पणियों को हटाने और संपादित करने की अनुमति नहीं देते हैं) - आपके पास पोस्ट के साथ कहीं भी दिखाने के लिए एक मूल्य है और कैशिंग के लिए एक कुंजी है।

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