Redis
 sql >> डेटाबेस >  >> NoSQL >> Redis

रेडिस के साथ Django में कैशिंग

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

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

निःशुल्क बोनस: एक मुफ्त Django लर्निंग रिसोर्स गाइड (पीडीएफ) तक पहुंच प्राप्त करने के लिए यहां क्लिक करें जो आपको टिप्स और ट्रिक्स के साथ-साथ पायथन + Django वेब एप्लिकेशन बनाते समय बचने के लिए सामान्य नुकसान दिखाता है।


रेडिस क्या है?

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



आरंभ करना

हमने आपको कैशिंग की अवधारणा से परिचित कराने के लिए एक उदाहरण एप्लिकेशन बनाया है। हमारे आवेदन का उपयोग करता है:

  • Django (v1.9.8)
  • Django डीबग टूलबार (v1.4)
  • django-redis (v4.4.3)
  • रेडिस (v3.2.0)

ऐप इंस्टॉल करें

रिपॉजिटरी को क्लोन करने से पहले, यदि आपके पास पहले से यह नहीं है, तो virtualenvwrapper स्थापित करें। यह एक ऐसा टूल है जो आपको विशिष्ट पायथन निर्भरता स्थापित करने देता है जिसकी आपकी परियोजना को आवश्यकता होती है, जिससे आप अपने ऐप के लिए अलग-अलग संस्करणों और पुस्तकालयों को लक्षित कर सकते हैं।

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

$ mkvirtualenv django-redis
(django-redis)$
<ब्लॉकक्वॉट>

नोट: mkvirtualenv . के साथ वर्चुअल वातावरण बनाना इसे सक्रिय भी करता है।

pip . के साथ सभी आवश्यक पायथन निर्भरताएं स्थापित करें , और फिर निम्न टैग चेकआउट करें:

(django-redis)$ git checkout tags/1

डेटाबेस बनाकर और नमूना डेटा के साथ इसे पॉप्युलेट करके उदाहरण ऐप की स्थापना समाप्त करें। एक सुपरयुसर भी बनाना सुनिश्चित करें, ताकि आप व्यवस्थापक साइट में लॉग इन कर सकें। नीचे दिए गए कोड उदाहरणों का पालन करें और फिर यह सुनिश्चित करने के लिए ऐप चलाने का प्रयास करें कि यह सही तरीके से काम कर रहा है। यह पुष्टि करने के लिए कि डेटा ठीक से लोड किया गया है, ब्राउज़र में व्यवस्थापक पृष्ठ पर जाएँ।

(django-redis)$ python manage.py makemigrations cookbook
(django-redis)$ python manage.py migrate
(django-redis)$ python manage.py createsuperuser
(django-redis)$ python manage.py loaddata cookbook/fixtures/cookbook.json
(django-redis)$ python manage.py runserver

एक बार जब आपके पास Django ऐप चल रहा हो, तो रेडिस इंस्टॉलेशन पर जाएं।



Redis इंस्टॉल करें

प्रलेखन में दिए गए निर्देशों का उपयोग करके रेडिस को डाउनलोड और इंस्टॉल करें। वैकल्पिक रूप से, आप apt-get . जैसे पैकेज मैनेजर का उपयोग करके Redis इंस्टॉल कर सकते हैं या होमब्रू आपके ओएस पर निर्भर करता है।

Redis सर्वर को एक नई टर्मिनल विंडो से चलाएँ।

$ redis-server

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

$ redis-cli ping
PONG

रेडिस विभिन्न कमांड के साथ एक एपीआई प्रदान करता है जिसका उपयोग डेवलपर डेटा स्टोर पर कार्य करने के लिए कर सकता है। Django django-redis का उपयोग करता है रेडिस में कमांड निष्पादित करने के लिए।

टेक्स्ट एडिटर में हमारे उदाहरण ऐप को देखते हुए, हम रेडिस कॉन्फ़िगरेशन को settings.py में देख सकते हैं। फ़ाइल। हम डिफ़ॉल्ट कैश को CACHES . के साथ परिभाषित करते हैं बिल्ट-इन django-redis . का उपयोग करके सेटिंग हमारे बैकएंड के रूप में कैश। रेडिस डिफ़ॉल्ट रूप से पोर्ट 6379 पर चलता है, और हम अपनी सेटिंग में उस स्थान को इंगित करते हैं। उल्लेख करने के लिए एक आखिरी बात यह है कि django-redis समान कुंजियों को अलग करने में मदद करने के लिए एक उपसर्ग और एक संस्करण के साथ प्रमुख नामों को जोड़ता है। इस मामले में, हमने उपसर्ग को "उदाहरण" के रूप में परिभाषित किया है।

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient"
        },
        "KEY_PREFIX": "example"
    }
}
<ब्लॉकक्वॉट>

नोट :हालांकि हमने कैश बैकएंड को कॉन्फ़िगर किया है, किसी भी व्यू फ़ंक्शन ने कैशिंग को लागू नहीं किया है।




ऐप्लिकेशन प्रदर्शन

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

जब हम कैशिंग लागू करते हैं, तो हम सर्वर को एक बार अनुरोध संसाधित करने देते हैं और फिर हम इसे अपने कैश में संग्रहीत करते हैं। जैसे ही हमारे एप्लिकेशन को उसी URL के लिए अनुरोध प्राप्त होते हैं, सर्वर हर बार नए सिरे से परिणामों को संसाधित करने के बजाय कैश से परिणाम खींचता है। आमतौर पर, हम संचित परिणामों पर रहने के लिए एक समय निर्धारित करते हैं, ताकि डेटा को समय-समय पर ताज़ा किया जा सके, जो कि पुराने डेटा की सेवा से बचने के लिए लागू करने के लिए एक महत्वपूर्ण कदम है।

निम्नलिखित मामलों के सत्य होने पर आपको अनुरोध के परिणाम को कैशिंग करने पर विचार करना चाहिए:

  • पेज को रेंडर करने में बहुत सारी डेटाबेस क्वेरी और/या व्यावसायिक तर्क शामिल हैं,
  • पृष्ठ पर आपके उपयोगकर्ता अक्सर आते हैं,
  • डेटा हर उपयोगकर्ता के लिए समान है,
  • और डेटा अक्सर नहीं बदलता है।

प्रदर्शन को मापने के द्वारा प्रारंभ करें

बेंचमार्किंग करके अपने आवेदन में प्रत्येक पृष्ठ की गति का परीक्षण करके शुरू करें कि आपका आवेदन अनुरोध प्राप्त करने के बाद कितनी जल्दी प्रतिक्रिया देता है।

इसे प्राप्त करने के लिए, हम लोडटेस्ट, एक HTTP लोड जेनरेटर का उपयोग करके अनुरोधों के फटने के साथ प्रत्येक पृष्ठ को नष्ट कर देंगे, और फिर अनुरोध दर पर पूरा ध्यान देंगे। इंस्टॉल करने के लिए ऊपर दिए गए लिंक पर जाएं। एक बार इंस्टाल हो जाने पर, /cookbook/ . के विरुद्ध परिणामों का परीक्षण करें यूआरएल पथ:

$ loadtest -n 100 -k  http://localhost:8000/cookbook/

ध्यान दें कि हम प्रति सेकंड लगभग 16 अनुरोधों को संसाधित कर रहे हैं:

Requests per second: 16

जब हम देखते हैं कि कोड क्या कर रहा है, तो हम प्रदर्शन को बेहतर बनाने के लिए परिवर्तन करने के तरीके के बारे में निर्णय ले सकते हैं। एप्लिकेशन /cookbook/ . के प्रत्येक अनुरोध के साथ डेटाबेस में 3 नेटवर्क कॉल करता है , और प्रत्येक कॉल को एक कनेक्शन खोलने और एक क्वेरी निष्पादित करने में समय लगता है। /cookbook/ पर जाएं अपने ब्राउज़र में URL और इस व्यवहार की पुष्टि करने के लिए Django डीबग टूलबार टैब का विस्तार करें। "एसक्यूएल" लेबल वाला मेनू ढूंढें और प्रश्नों की संख्या पढ़ें:

रसोई की किताब/services.py

from cookbook.models import Recipe


def get_recipes():
    # Queries 3 tables: cookbook_recipe, cookbook_ingredient,
    # and cookbook_food.
    return list(Recipe.objects.prefetch_related('ingredient_set__food'))

रसोई की किताब/views.py

from django.shortcuts import render
from cookbook.services import get_recipes


def recipes_view(request):
    return render(request, 'cookbook/recipes.html', {
        'recipes': get_recipes()
    })

एप्लिकेशन कुछ संभावित महंगे तर्क के साथ एक टेम्पलेट भी प्रस्तुत करता है।

<html>
<head>
  <title>Recipes</title>
</head>
<body>
{% for recipe in recipes %}
  <h1>{{ recipe.name }}</h1>
    <p>{{ recipe.desc }}</p>
  <h2>Ingredients</h2>
  <ul>
    {% for ingredient in recipe.ingredient_set.all %}
    <li>{{ ingredient.desc }}</li>
    {% endfor %}
  </ul>
  <h2>Instructions</h2>
    <p>{{ recipe.instructions }}</p>
{% endfor %}
</body>
</html>


कैशिंग लागू करें

कल्पना कीजिए कि जैसे-जैसे उपयोगकर्ता हमारी साइट पर आना शुरू करते हैं, वैसे-वैसे हमारा एप्लिकेशन कितने नेटवर्क कॉल्स करेगा। यदि 1,000 उपयोगकर्ता एपीआई को हिट करते हैं जो कुकबुक रेसिपी को पुनः प्राप्त करता है, तो हमारा एप्लिकेशन डेटाबेस को 3,000 बार क्वेरी करेगा और प्रत्येक अनुरोध के साथ एक नया टेम्प्लेट प्रदान किया जाएगा। यह संख्या केवल हमारे आवेदन के पैमाने के रूप में बढ़ती है। सौभाग्य से, यह दृश्य कैशिंग के लिए एक उत्कृष्ट उम्मीदवार है। रसोई की किताब में व्यंजन शायद ही कभी बदलते हैं। साथ ही, चूंकि कुकबुक देखना ऐप का केंद्रीय विषय है, इसलिए रेसिपी को पुनः प्राप्त करने वाले एपीआई को बार-बार कॉल करने की गारंटी है।

नीचे दिए गए उदाहरण में, हम कैशिंग का उपयोग करने के लिए व्यू फ़ंक्शन को संशोधित करते हैं। जब फ़ंक्शन चलता है, तो यह जांचता है कि दृश्य कुंजी कैश में है या नहीं। यदि कुंजी मौजूद है, तो ऐप कैश से डेटा पुनर्प्राप्त करता है और उसे वापस कर देता है। यदि नहीं, तो Django डेटाबेस से पूछताछ करता है और फिर परिणाम को कैश में दृश्य कुंजी के साथ छिपा देता है। पहली बार जब यह फ़ंक्शन चलाया जाता है, तो Django डेटाबेस से पूछताछ करेगा और टेम्पलेट प्रस्तुत करेगा, और फिर कैश में डेटा स्टोर करने के लिए रेडिस को नेटवर्क कॉल भी करेगा। फ़ंक्शन के लिए प्रत्येक बाद की कॉल डेटाबेस और व्यावसायिक तर्क को पूरी तरह से बायपास कर देगी और रेडिस कैश को क्वेरी करेगी।

example/settings.py

# Cache time to live is 15 minutes.
CACHE_TTL = 60 * 15

रसोई की किताब/views.py

from django.conf import settings
from django.core.cache.backends.base import DEFAULT_TIMEOUT
from django.shortcuts import render
from django.views.decorators.cache import cache_page
from cookbook.services import get_recipes

CACHE_TTL = getattr(settings, 'CACHE_TTL', DEFAULT_TIMEOUT)


@cache_page(CACHE_TTL)
def recipes_view(request):
    return render(request, 'cookbook/recipes.html', {
        'recipes': get_recipes()
    })

ध्यान दें कि हमने @cache_page() जोड़ा है डेकोरेटर टू व्यू फंक्शन, साथ में जीने का समय। /cookbook/ पर जाएं फिर से यूआरएल और Django डीबग टूलबार की जांच करें। हम देखते हैं कि 3 डेटाबेस क्वेश्चन किए जाते हैं और 3 कॉल कैश में की जाती हैं ताकि कुंजी की जांच की जा सके और फिर उसे सेव किया जा सके। Django दो कुंजी सहेजता है (शीर्षलेख के लिए 1 कुंजी और प्रस्तुत पृष्ठ सामग्री के लिए 1 कुंजी)। पृष्ठ को पुनः लोड करें और देखें कि पृष्ठ गतिविधि कैसे बदलती है। दूसरी बार, डेटाबेस में 0 कॉल किए जाते हैं और कैश में 2 कॉल किए जाते हैं। हमारा पेज अब कैशे से परोसा जा रहा है!

जब हम अपने प्रदर्शन परीक्षण को फिर से चलाते हैं, तो हम देखते हैं कि हमारा एप्लिकेशन तेजी से लोड हो रहा है।

$ loadtest -n 100 -k  http://localhost:8000/cookbook/

कैशिंग ने कुल लोड में सुधार किया, और अब हम प्रति सेकंड 21 अनुरोधों का समाधान कर रहे हैं, जो कि हमारी आधार रेखा से 5 अधिक है:

Requests per second: 21


CLI से Redis की जांच करना

इस बिंदु पर हम Redis सर्वर पर संग्रहीत होने वाली चीज़ों को देखने के लिए Redis CLI का उपयोग कर सकते हैं। रेडिस कमांड लाइन में, keys * दर्ज करें कमांड, जो किसी भी पैटर्न से मेल खाने वाली सभी कुंजियाँ लौटाता है। आपको "example:1:views.decorators.cache.cache_page" नामक एक कुंजी दिखाई देनी चाहिए। याद रखें, "उदाहरण" हमारा मुख्य उपसर्ग है, "1" संस्करण है, और "views.decorators.cache.cache_page" वह नाम है जो Django कुंजी देता है। कुंजी नाम की प्रतिलिपि बनाएँ और इसे get . के साथ दर्ज करें आज्ञा। आपको प्रदान की गई HTML स्ट्रिंग देखनी चाहिए।

$ redis-cli -n 1
127.0.0.1:6379[1]> keys *
1) "example:1:views.decorators.cache.cache_header"
2) "example:1:views.decorators.cache.cache_page"
127.0.0.1:6379[1]> get "example:1:views.decorators.cache.cache_page"
<ब्लॉकक्वॉट>

नोट: flushallचलाएं डेटा स्टोर से सभी कुंजियों को साफ़ करने के लिए रेडिस सीएलआई पर कमांड। फिर, आप कैश के समाप्त होने की प्रतीक्षा किए बिना इस ट्यूटोरियल के चरणों को फिर से चला सकते हैं।




रैप-अप

HTTP अनुरोधों को संसाधित करना महंगा है, और जैसे-जैसे आपका एप्लिकेशन लोकप्रियता में बढ़ता है, यह लागत बढ़ती जाती है। कुछ उदाहरणों में, आप कैशिंग को लागू करके अपने सर्वर द्वारा किए जाने वाले संसाधन की मात्रा को बहुत कम कर सकते हैं। इस ट्यूटोरियल ने रेडिस के साथ Django में कैशिंग की मूल बातें छुआ, लेकिन इसने केवल एक जटिल विषय की सतह को स्किम किया।

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

निःशुल्क बोनस: एक मुफ्त Django लर्निंग रिसोर्स गाइड (पीडीएफ) तक पहुंच प्राप्त करने के लिए यहां क्लिक करें जो आपको टिप्स और ट्रिक्स के साथ-साथ पायथन + Django वेब एप्लिकेशन बनाते समय बचने के लिए सामान्य नुकसान दिखाता है।

उदाहरण एप्लिकेशन में स्रोत कोड के साथ खेलें और जैसा कि आप Django के साथ विकसित करना जारी रखते हैं, हमेशा प्रदर्शन को ध्यान में रखना याद रखें।



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. रेडिस, क्या कोई विषय (पब/उप) हमेशा कम से कम एक ग्राहक तक पहुंचाया जाएगा?

  2. पायथन में रेडिस कनेक्शन पूल का उपयोग करने का सही तरीका

  3. रेडिस कैश से सीधे सामग्री परोसने के लिए nginx का उपयोग करना

  4. रेडिस के साथ पहला कदम

  5. साइडकीक की नौकरियों के निष्पादन समय को कम करें