sql >> Databáze >  >> NoSQL >> Memcached

Python + Memcached:Efektivní ukládání do mezipaměti v distribuovaných aplikacích

Při psaní aplikací v Pythonu je důležité ukládání do mezipaměti. Použití mezipaměti k zamezení přepočítávání dat nebo přístupu k pomalé databázi vám může poskytnout skvělé zvýšení výkonu.

Python nabízí vestavěné možnosti ukládání do mezipaměti, od jednoduchého slovníku po úplnější datovou strukturu, jako je functools.lru_cache . Posledně jmenovaný může ukládat do mezipaměti jakoukoli položku pomocí algoritmu nejméně nedávno použitého k omezení velikosti mezipaměti.

Tyto datové struktury jsou však z definice lokální k vašemu procesu Python. Když několik kopií vaší aplikace běží na velké platformě, použití datové struktury v paměti neumožňuje sdílení obsahu uloženého v mezipaměti. To může být problém u rozsáhlých a distribuovaných aplikací.

Proto, když je systém distribuován po síti, potřebuje také mezipaměť, která je distribuována po síti. V současné době existuje spousta síťových serverů, které nabízejí možnost ukládání do mezipaměti – již jsme probrali, jak používat Redis pro ukládání do mezipaměti s Django.

Jak uvidíte v tomto tutoriálu, memcached je další skvělá možnost distribuovaného ukládání do mezipaměti. Po rychlém úvodu do základního používání memcached se dozvíte o pokročilých vzorech, jako je „cachovat a nastavit“ a používat záložní mezipaměti, abyste se vyhnuli problémům s výkonem studené mezipaměti.


Instalace memcached

Memcached je k dispozici pro mnoho platforem:

  • Pokud používáte Linux , můžete jej nainstalovat pomocí apt-get install memcached nebo yum install memcached . Tím se nainstaluje memcached z předem sestaveného balíčku, ale můžete také sestavit memcached ze zdroje, jak je vysvětleno zde.
  • Pro macOS , použití Homebrew je nejjednodušší možností. Stačí spustit brew install memcached po instalaci správce balíčků Homebrew.
  • V systému Windows , museli byste si memcached zkompilovat sami nebo najít předkompilované binární soubory.

Po instalaci se uloží do mezipaměti lze jednoduše spustit voláním memcached příkaz:

$ memcached

Než budete moci pracovat s memcached z Python-landu, musíte si nainstalovat klienta memcached knihovna. V další části uvidíte, jak to udělat, spolu s některými základními operacemi přístupu k mezipaměti.



Ukládání a načítání hodnot z mezipaměti pomocí Pythonu

Pokud jste nikdy nepoužili memcached , je to docela snadné pochopit. V podstatě poskytuje obří síťově dostupný slovník. Tento slovník má několik vlastností, které se liší od klasického slovníku Pythonu, zejména:

  • Klíče a hodnoty musí být bajty
  • Klíče a hodnoty se po uplynutí doby platnosti automaticky smažou

Proto jsou dvě základní operace pro interakci s memcached jsou set a get . Jak jste možná uhodli, používají se k přiřazení hodnoty klíči nebo k získání hodnoty z klíče.

Moje preferovaná Python knihovna pro interakci s memcached je pymemcache -Doporučuji používat. Můžete jej jednoduše nainstalovat pomocí pip:

$ pip install pymemcache

Následující kód ukazuje, jak se můžete připojit k memcached a použijte ji jako síťově distribuovanou mezipaměť ve vašich aplikacích Python:

>>> from pymemcache.client import base

# Don't forget to run `memcached' before running this next line:
>>> client = base.Client(('localhost', 11211))

# Once the client is instantiated, you can access the cache:
>>> client.set('some_key', 'some value')

# Retrieve previously set data again:
>>> client.get('some_key')
'some value'

uloženo do mezipaměti síťový protokol je opravdu jednoduchý a jeho implementace extrémně rychlá, díky čemuž je užitečné ukládat data, která by jinak byla pomalá při získávání z kanonického zdroje dat nebo při opětovném výpočtu:

I když je tento příklad dostatečně přímočarý, umožňuje ukládat n-tice klíč/hodnota přes síť a přistupovat k nim prostřednictvím více distribuovaných běžících kopií vaší aplikace. To je zjednodušené, ale silné. A je to skvělý první krok k optimalizaci vaší aplikace.



Automaticky vyprší platnost dat uložených v mezipaměti

Při ukládání dat do memcached , můžete nastavit dobu vypršení platnosti – maximální počet sekund pro memcached udržet klíč a hodnotu. Po této prodlevě se memcached automaticky odstraní klíč z mezipaměti.

Na co byste měli nastavit tento čas mezipaměti? Pro toto zpoždění neexistuje žádné magické číslo a bude zcela záviset na typu dat a aplikace, se kterou pracujete. Může to být několik sekund nebo několik hodin.

Zneplatnění mezipaměti , který definuje, kdy odstranit mezipaměť, protože není synchronizována s aktuálními daty, je také něco, co vaše aplikace bude muset zvládnout. Zvláště pokud prezentujete data, která jsou příliš stará nebo zastaralá je třeba se vyhnout.

Zde opět neexistuje žádný kouzelný recept; záleží na typu aplikace, kterou vytváříte. Existuje však několik odlehlých případů, které by se měly řešit – které jsme ve výše uvedeném příkladu ještě nepokryli.

Server pro ukládání do mezipaměti nemůže růst donekonečna – paměť je omezený zdroj. Proto budou klíče mezipaměti vyprázdněny, jakmile bude potřebovat více místa pro uložení dalších věcí.

Některým klíčům může také vypršet platnost, protože dosáhly doby vypršení platnosti (někdy také nazývané „time-to-live“ nebo TTL). V těchto případech jsou data ztracena a kanonický zdroj dat musí být znovu dotazován.

Zní to složitější, než to ve skutečnosti je. Při práci s memcached v Pythonu můžete obecně pracovat s následujícím vzorem:

from pymemcache.client import base


def do_some_query():
    # Replace with actual querying code to a database,
    # a remote REST API, etc.
    return 42


# Don't forget to run `memcached' before running this code
client = base.Client(('localhost', 11211))
result = client.get('some_key')

if result is None:
    # The cache is empty, need to get the value
    # from the canonical source:
    result = do_some_query()

    # Cache the result for next time:
    client.set('some_key', result)

# Whether we needed to update the cache or not,
# at this point you can work with the data
# stored in the `result` variable:
print(result)

Poznámka: Manipulace s chybějícími klíči je povinná kvůli normálním operacím splachování. Je také povinné zpracovat scénář studené mezipaměti, tj. když memcached byla právě zahájena. V takovém případě bude mezipaměť zcela prázdná a je třeba ji zcela znovu naplnit, jeden požadavek po druhém.

To znamená, že byste měli všechna data uložená v mezipaměti považovat za pomíjivá. A nikdy byste neměli očekávat, že mezipaměť obsahuje hodnotu, kterou jste do ní dříve zapsali.



Zahřívání studené mezipaměti

Některým scénářům studené mezipaměti nelze zabránit, například memcached pád. Někteří však mohou, například migrací na nový memcached server.

Když je možné předvídat, že nastane scénář studené vyrovnávací paměti, je lepší se tomu vyhnout. Mezipaměť, kterou je třeba znovu naplnit, znamená, že kanonické úložiště dat uložených v mezipaměti bude najednou masivně zasaženo všemi uživateli mezipaměti, kteří postrádají data mezipaměti (známé také jako problém hromového stáda.)

pymemcache poskytuje třídu s názvem FallbackClient což pomáhá při implementaci tohoto scénáře, jak je ukázáno zde:

from pymemcache.client import base
from pymemcache import fallback


def do_some_query():
    # Replace with actual querying code to a database,
    # a remote REST API, etc.
    return 42


# Set `ignore_exc=True` so it is possible to shut down
# the old cache before removing its usage from 
# the program, if ever necessary.
old_cache = base.Client(('localhost', 11211), ignore_exc=True)
new_cache = base.Client(('localhost', 11212))

client = fallback.FallbackClient((new_cache, old_cache))

result = client.get('some_key')

if result is None:
    # The cache is empty, need to get the value 
    # from the canonical source:
    result = do_some_query()

    # Cache the result for next time:
    client.set('some_key', result)

print(result)

FallbackClient dotazy staré mezipaměti předané svému konstruktoru, respektujíc pořadí. V tomto případě bude vždy nejprve dotázán nový cache server a v případě vynechání cache bude dotázán starý server, aby se předešlo možnému návratu k primárnímu zdroji dat.

Pokud je nastaven jakýkoli klíč, bude nastaven pouze na novou mezipaměť. Po nějaké době může být stará cache vyřazena z provozu a FallbackClient lze nahradit řízenou pomocí new_cache klient.



Zkontrolovat a nastavit

Při komunikaci se vzdálenou mezipamětí se vrací obvyklý problém souběžnosti:může existovat několik klientů, kteří se pokoušejí o přístup ke stejnému klíči současně. uloženo do mezipaměti poskytuje kontrolu a nastavení operace, zkráceno na CAS , která pomáhá tento problém vyřešit.

Nejjednodušším příkladem je aplikace, která chce spočítat počet uživatelů, které má. Pokaždé, když se návštěvník připojí, počítadlo se zvýší o 1. Pomocí memcached , jednoduchá implementace by byla:

def on_visit(client):
    result = client.get('visitors')
    if result is None:
        result = 1
    else:
        result += 1
    client.set('visitors', result)

Co se však stane, když se dvě instance aplikace pokusí aktualizovat tento čítač současně?

První volání client.get('visitors') vrátí stejný počet návštěvníků pro oba, řekněme, že je to 42. Pak oba sečtou 1, spočítají 43 a nastaví počet návštěvníků na 43. Toto číslo je špatné a výsledek by měl být 44, tj. 42 + 1 + 1.

K vyřešení tohoto problému souběžnosti byla operace CAS memcached je šikovný. Následující úryvek implementuje správné řešení:

def on_visit(client):
    while True:
        result, cas = client.gets('visitors')
        if result is None:
            result = 1
        else:
            result += 1
        if client.cas('visitors', result, cas):
            break

gets metoda vrací hodnotu, stejně jako get metoda, ale také vrací hodnotu CAS .

Co je v této hodnotě není relevantní, ale používá se pro další metodu cas volání. Tato metoda je ekvivalentní set operace, kromě toho, že selže, pokud se hodnota od gets změnila úkon. V případě úspěchu se smyčka přeruší. V opačném případě se operace restartuje od začátku.

Ve scénáři, kdy se dvě instance aplikace pokoušejí aktualizovat čítač současně, pouze jedné se podaří přesunout čítač z 42 na 43. Druhá instance dostane False hodnotu vrácenou client.cas zavolejte a musíte opakovat smyčku. Tentokrát získá hodnotu 43, zvýší ji na 44 a její cas hovor bude úspěšný, čímž se náš problém vyřeší.

Zvýšení počítadla je zajímavé jako příklad pro vysvětlení, jak CAS funguje, protože je zjednodušující. Nicméně, memcached také poskytuje incr a decr metody pro zvýšení nebo snížení celého čísla v jednom požadavku namísto provádění více gets /cas hovory. V aplikacích reálného světa gets a cas se používají pro složitější datový typ nebo operace

Většina serverů vzdáleného ukládání do mezipaměti a datových úložišť poskytuje takový mechanismus, aby se zabránilo problémům se souběžností. Je důležité, abyste si byli vědomi těchto případů, abyste mohli správně využívat jejich funkce.



Víc než ukládání do mezipaměti

Jednoduché techniky uvedené v tomto článku vám ukázaly, jak snadné je využít memcached pro urychlení výkonu vaší aplikace Python.

Pouhým použitím dvou základních operací „set“ a „get“ můžete často urychlit načítání dat nebo se vyhnout opakovanému přepočítávání výsledků. S memcached můžete sdílet mezipaměť napříč velkým počtem distribuovaných uzlů.

Další, pokročilejší vzory, které jste viděli v tomto tutoriálu, jako je Check And Set (CAS) operace vám umožní aktualizovat data uložená v mezipaměti souběžně ve více vláknech nebo procesech Pythonu a zároveň se vyhnout poškození dat.

Pokud se chcete dozvědět více o pokročilých technikách psaní rychlejších a škálovatelnějších aplikací Python, podívejte se na Scaling Python. Pokrývá mnoho pokročilých témat, jako je distribuce sítě, systémy řazení do fronty, distribuované hashování a profilování kódu.



  1. Nelze najít modul '../build/Release/bson'] kód:'MODULE_NOT_FOUND' } js-bson:Nepodařilo se načíst rozšíření c++ bson pomocí čisté verze JS

  2. Cassandra vs. MongoDB:který z nich byste si měli vybrat

  3. Konzistentní hašování jako způsob škálování zápisů

  4. Unikátní bodování pro redis leaderboard