sql >> Databáze >  >> NoSQL >> Redis

Ukládání do mezipaměti v Django s Redis

Výkon aplikace je zásadní pro úspěch vašeho produktu. V prostředí, kde uživatelé očekávají dobu odezvy webu kratší než jednu sekundu, lze důsledky pomalé aplikace měřit v dolarech a centech. I když nic neprodáváte, rychlé načítání stránek zlepšuje zážitek z návštěvy vašeho webu.

Všechno, co se děje na serveru mezi okamžikem přijetí požadavku a okamžikem, kdy vrátí odpověď, zvyšuje dobu potřebnou k načtení stránky. Obecně platí, že čím více zpracování můžete na serveru odstranit, tím rychleji bude vaše aplikace fungovat. Ukládání dat do mezipaměti po jejich zpracování a jejich následné poskytování z mezipaměti při příštím vyžádání je jedním ze způsobů, jak zmírnit stres na serveru. V tomto tutoriálu prozkoumáme některé faktory, které zabraňují vaší aplikaci, a ukážeme si, jak implementovat ukládání do mezipaměti s Redis, aby se zabránilo jejich účinkům.

Box zdarma: Kliknutím sem získáte přístup k bezplatné příručce Django Learning Resources Guide (PDF), která vám ukáže tipy a triky a také běžné nástrahy, kterým je třeba se vyhnout při vytváření webových aplikací Python + Django.


Co je Redis?

Redis je úložiště datových struktur v paměti, které lze použít jako modul mezipaměti. Protože uchovává data v paměti RAM, může je Redis dodat velmi rychle. Redis není jediný produkt, který můžeme použít pro ukládání do mezipaměti. Memcached je další populární systém ukládání do mezipaměti, ale mnoho lidí souhlasí s tím, že Redis je ve většině případů lepší než Memcached. Osobně se nám líbí, jak snadné je nastavit a používat Redis pro jiné účely, jako je Redis Queue.



Začínáme

Vytvořili jsme ukázkovou aplikaci, která vám představí koncept ukládání do mezipaměti. Naše aplikace používá:

  • Django (v1.9.8)
  • Django Debug Toolbar (v1.4)
  • django-redis (v4.4.3)
  • Redis (v3.2.0)

Nainstalujte aplikaci

Před klonováním úložiště nainstalujte virtualenvwrapper, pokud jej ještě nemáte. Toto je nástroj, který vám umožní nainstalovat specifické závislosti Pythonu, které váš projekt potřebuje, a umožnit vám tak zacílit na verze a knihovny požadované vaší aplikací samostatně.

Dále změňte adresáře, kde máte projekty, a naklonujte ukázkové úložiště aplikací. Po dokončení změňte adresáře na klonované úložiště a poté vytvořte nové virtuální prostředí pro ukázkovou aplikaci pomocí mkvirtualenv příkaz:

$ mkvirtualenv django-redis
(django-redis)$

POZNÁMKA: Vytvoření virtuálního prostředí pomocí mkvirtualenv ji také aktivuje.

Nainstalujte všechny požadované závislosti Pythonu pomocí pip a poté si zarezervujte následující značku:

(django-redis)$ git checkout tags/1

Dokončete nastavení ukázkové aplikace vytvořením databáze a jejím naplněním ukázkovými daty. Nezapomeňte také vytvořit superuživatele, abyste se mohli přihlásit na stránku správce. Postupujte podle níže uvedených příkladů kódu a poté zkuste aplikaci spustit, abyste se ujistili, že funguje správně. Navštivte stránku správce v prohlížeči a ověřte, zda byla data správně načtena.

(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

Jakmile budete mít spuštěnou aplikaci Django, přejděte k instalaci Redis.



Nainstalujte Redis

Stáhněte a nainstalujte Redis pomocí pokynů uvedených v dokumentaci. Alternativně můžete Redis nainstalovat pomocí správce balíčků, jako je apt-get nebo homebrew v závislosti na vašem operačním systému.

Spusťte server Redis z nového okna terminálu.

$ redis-server

Dále spusťte rozhraní příkazového řádku (CLI) Redis v jiném okně terminálu a otestujte, zda se připojuje k serveru Redis. Ke kontrole klíčů, které přidáme do mezipaměti, použijeme Redis CLI.

$ redis-cli ping
PONG

Redis poskytuje rozhraní API s různými příkazy, které může vývojář použít k jednání s úložištěm dat. Django používá django-redis pro provádění příkazů v Redis.

Při pohledu na naši ukázkovou aplikaci v textovém editoru můžeme vidět konfiguraci Redis v settings.py soubor. Výchozí mezipaměť definujeme pomocí CACHES nastavení pomocí vestavěného django-redis cache jako náš backend. Redis standardně běží na portu 6379 a v našem nastavení na toto umístění odkazujeme. Poslední věc, kterou je třeba zmínit, je django-redis připojuje názvy klíčů předponou a verzí, aby pomohly rozlišit podobné klíče. V tomto případě jsme definovali předponu jako „příklad“.

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"
    }
}

POZNÁMKA :Přestože jsme nakonfigurovali backend mezipaměti, žádná z funkcí zobrazení neimplementovala ukládání do mezipaměti.




Výkon aplikace

Jak jsme zmínili na začátku tohoto tutoriálu, vše, co server dělá pro zpracování požadavku, zpomaluje dobu načítání aplikace. Režie zpracování při běhu obchodní logiky a vykreslovacích šablon může být značná. Latence sítě ovlivňuje dobu, kterou trvá dotazování databáze. Tyto faktory vstupují do hry pokaždé, když klient odešle HTTP požadavek na server. Když uživatelé zahajují mnoho požadavků za sekundu, vliv na výkon je patrný, protože server pracuje na jejich zpracování.

Když implementujeme ukládání do mezipaměti, necháme server jednou zpracovat požadavek a poté jej uložíme do naší mezipaměti. Protože naše aplikace přijímá požadavky na stejnou adresu URL, server stahuje výsledky z mezipaměti místo toho, aby je pokaždé zpracovával znovu. Obvykle nastavujeme dobu trvání výsledků uložených v mezipaměti, aby bylo možné data pravidelně obnovovat, což je důležitý krok k implementaci, abychom se vyhnuli poskytování zastaralých dat.

Uložení výsledku požadavku do mezipaměti byste měli zvážit, pokud jsou splněny následující případy:

  • vykreslování stránky vyžaduje mnoho databázových dotazů a/nebo obchodní logiky,
  • stránku často navštěvují vaši uživatelé,
  • data jsou pro každého uživatele stejná,
  • a data se často nemění.

Začněte měřením výkonu

Začněte testováním rychlosti každé stránky ve vaší aplikaci srovnáváním, jak rychle vaše aplikace vrací odpověď po obdržení požadavku.

Abychom toho dosáhli, zahrneme každou stránku sérií požadavků pomocí loadtestu, generátoru zatížení HTTP, a poté budeme věnovat velkou pozornost míře požadavků. Pro instalaci navštivte výše uvedený odkaz. Po instalaci otestujte výsledky proti /cookbook/ Cesta URL:

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

Všimněte si, že zpracováváme asi 16 požadavků za sekundu:

Requests per second: 16

Když se podíváme na to, co kód dělá, můžeme se rozhodnout, jak provést změny ke zlepšení výkonu. Aplikace provede 3 síťová volání do databáze s každým požadavkem na /cookbook/ a každé volání trvá nějakou dobu, než se otevře připojení a provede dotaz. Navštivte /cookbook/ URL ve vašem prohlížeči a rozbalte kartu Django Debug Toolbar, abyste toto chování potvrdili. Najděte nabídku označenou „SQL“ a přečtěte si počet dotazů:

kuchařka/služby.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'))

kuchařka/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()
    })

Aplikace také vykresluje šablonu s nějakou potenciálně nákladnou logikou.

<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>


Implementujte ukládání do mezipaměti

Představte si celkový počet síťových hovorů, které naše aplikace provede, když uživatelé začnou navštěvovat naše stránky. Pokud 1 000 uživatelů narazí na API, které načítá recepty z kuchařek, naše aplikace se dotazuje databáze 3 000krát a s každým požadavkem se vykreslí nová šablona. Toto číslo roste pouze s tím, jak se naše aplikace škáluje. Naštěstí je tento pohled skvělým kandidátem na ukládání do mezipaměti. Recepty v kuchařce se jen zřídka mění, pokud vůbec. Vzhledem k tomu, že hlavním tématem aplikace je prohlížení kuchařek, je zaručeno, že API načítající recepty bude často voláno.

V níže uvedeném příkladu upravujeme funkci zobrazení tak, aby používala ukládání do mezipaměti. Když se funkce spustí, zkontroluje, zda je klíč zobrazení v mezipaměti. Pokud klíč existuje, aplikace načte data z mezipaměti a vrátí je. Pokud ne, Django se dotáže na databázi a poté uloží výsledek do mezipaměti pomocí klíče zobrazení. Při prvním spuštění této funkce se Django zeptá databáze a vykreslí šablonu a poté také provede síťové volání do Redis, aby data uložila do mezipaměti. Každé následující volání funkce zcela obejde databázi a obchodní logiku a bude se dotazovat na mezipaměť Redis.

example/settings.py

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

kuchařka/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()
    })

Všimněte si, že jsme přidali @cache_page() dekoratér na funkci zobrazení, spolu s časem žít. Navštivte /cookbook/ URL znovu a prozkoumejte Django Debug Toolbar. Vidíme, že jsou provedeny 3 databázové dotazy a 3 volání do mezipaměti za účelem kontroly klíče a následného uložení. Django ukládá dva klíče (1 klíč pro záhlaví a 1 klíč pro vykreslený obsah stránky). Znovu načtěte stránku a sledujte, jak se změní aktivita stránky. Podruhé se provede 0 volání do databáze a 2 volání do mezipaměti. Naše stránka je nyní obsluhována z mezipaměti!

Když znovu spustíme naše testy výkonu, vidíme, že se naše aplikace načítá rychleji.

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

Ukládání do mezipaměti zlepšilo celkové zatížení a nyní řešíme 21 požadavků za sekundu, což je o 5 více, než je naše základní hodnota:

Requests per second: 21


Kontrola Redis pomocí CLI

V tomto okamžiku můžeme použít Redis CLI, abychom se podívali na to, co se ukládá na serveru Redis. Na příkazovém řádku Redis zadejte keys * příkaz, který vrátí všechny klíče odpovídající libovolnému vzoru. Měli byste vidět klíč s názvem „example:1:views.decorators.cache.cache_page“. Pamatujte, že „example“ je naše předpona klíče, „1“ je verze a „views.decorators.cache.cache_page“ je název, který Django dává klíči. Zkopírujte název klíče a zadejte jej pomocí get příkaz. Měli byste vidět vykreslený řetězec 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"

POZNÁMKA: Spusťte flushall příkaz na Redis CLI k vymazání všech klíčů z úložiště dat. Poté můžete znovu projít kroky v tomto tutoriálu, aniž byste museli čekat na vypršení platnosti mezipaměti.




Shrnutí

Zpracování požadavků HTTP je nákladné a tyto náklady se zvyšují s rostoucí popularitou vaší aplikace. V některých případech můžete výrazně snížit množství zpracování, které váš server provádí, implementací ukládání do mezipaměti. Tento tutoriál se dotkl základů ukládání do mezipaměti v Django s Redisem, ale pouze zběžně prohlédl povrch složitého tématu.

Implementace ukládání do mezipaměti v robustní aplikaci má mnoho úskalí a problémů. Kontrola toho, co se ukládá do mezipaměti a na jak dlouho, je těžké. Zneplatnění mezipaměti je jednou z těžkých věcí v informatice. Zajištění, že k soukromým datům mají přístup pouze zamýšlení uživatelé, je bezpečnostní problém a při ukládání do mezipaměti je třeba s ním zacházet velmi opatrně.

Box zdarma: Kliknutím sem získáte přístup k bezplatné příručce Django Learning Resources Guide (PDF), která vám ukáže tipy a triky a také běžné nástrahy, kterým je třeba se vyhnout při vytváření webových aplikací Python + Django.

Pohrajte si se zdrojovým kódem v ukázkové aplikaci a jak budete pokračovat ve vývoji s Django, nezapomeňte vždy myslet na výkon.



  1. Nepodařilo se připojit Mongoose k Atlasu

  2. Jak nakonfigurovat cluster MongoDB, který podporuje relace?

  3. Redis seznam vnořených klíčů

  4. Jak implementovat server push v rámci Flask?