SlideShare uma empresa Scribd logo
1 de 40
Baixar para ler offline
Kdyby/Redis
@ProchazkaFilip - @Damejidlo
Jaký je plán?
- řekneme si co je Redis
- co umí kdyby/redis
- zprovozníme ho
- profit
Co je Redis?
- nízkoúrovňová databáze
- s datovými strukturami
- se scriptováním v LUA
- serializuje se na disk
- jednovláknový
Redis umí datové struktury od jednoduchých key:value, přes seznamy a hashe po seřazené sety. Je možné mu poslat script v LUA který evalne přímo nad
databázi, tedy si ušetříte hromadu komunikace. Další killer feature oproti memcache je i serializace na disk, což z něj dělá perfektního kanditáta pro session.
.. a umí ještě
- databáze (forma namespace)
- transakce (optimistic locking)
- pub/sub
- replikace
.. a hlavně
Je ve všem stejně rychlý
nebo rychlejší
než memcached
První dva bottlenecky v Nette?
session a journal
Výchozí session file storage je super, ale od určité návštěvnostni zvládá s přehledem zabíjet stránku.
Journal v Nette je velice jednoduchá databáze, do které se ukládá jaké mají data v cachi tagy a priority pro mazání. Journal není tak úplně bottleneck pokud
nepoužíváte tagy, ovšem pokud je používáte, tak narazíte na problémy při větší zátěži, nebo když do něj chce zapisovat hodně dat.
Na co je Redis super?
- session
- cache
- je to přece databáze!
Redis se dá použít nejenom na cachování a sessions, ale je to i plnohodnotná databáze a tedy do ní můžete přešunout i jiné části aplikace a zefektivnit ji tím.
Instalace: Redis
Redis:
http://redis.io/download
PHP Extension:
http://pecl.php.net/package/redis
Je potřeba nainstalovat nejenom samotnou databázi Redis, ale taky i PHP extension, abychom z rychlosti vytřískali maximum.
Instalace: Kdyby/Redis
$ composer require kdyby/redis:~3.0
app/config/config.neon
extensions:
redis: KdybyRedisDIRedisExtension
Samozřejmostí je instalace Kdyby/Redis přes composer a compiler extension. Řada 3.0 je pro Nette 2.1 a dev.
Session
Session
Výchozí PHP session storage
stojí za úplný ho... uby!
Největší dvě úzká hrdla jsou čištění starých session a limit počtu souborů na složku ve většine filesystémů. Obojí jde řešit, ale přoč tím ztrácet čas když máme
možnost použít Redis.
Session: nativní storage
session.save_handler = redis
session.save_path
= "tcp://127.0.0.1:6379"
zapíná se pomocí:
redis:
session: on
Nativní storage využívá interního mechanismu v PHP na ukládání session a handleru který dodává phpredis (ten php extension). Důležité ovšem je, že tato
forma ukládání session neblokuje a možná ani nikdy nebude, protože Redis sám o sobě nepodporuje zamykání.
Session: emulovaný storage
SessionHandlerInterface
zapíná se pomocí:
redis:
session: {native: off}
Kdyby/Redis ale obsahuje i vlastní implementaci, která využívá jiný PHP mechanismus na ukládání sessions. Proč psát vlastní? Protože tato implementace
dokáže session zamykat, jako standardní filesystemová. Díky tomu se nám nebudou přepisovat a ztrácet data. Obě implementace jsou kompatibilní a lze je
libovolně přepínat bez strachu ze ztráty dat.
Cache - RedisStorage
Cache: CachingIStorage
redis:
storage: on
journal: on
Kdyby/Redis obsahuje oddělené implementace journalu a cache a je možné obě dvě používat samostatně, ale ve výsledku dává smysl hlavně použití obou
zároveň.
Cache: rychlost
class BenchmarkFileStorage
implements NetteCachingIStorage
{
function __construct(NetteCachingIStorage $storage);
function read($key) {
try { $time = microtime(TRUE);
return $this->storage->read($key);
} finally {$this->calls[]=microtime(TRUE)-$time;}
}
Večer před posobotou jsem se rozhodl změřit rozdíl rychlosti FS storage oproti Redisu abych mohl ohromit slečny v publiku a napsal jsem si vlastní storage
dekorátor, kterým jsem plánoval měřit dobu strávenou v cachi.
Cache: rychlost
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=12
opcache.max_accelerated_files=12000
opcache.validate_timestamps=0
opcache.fast_shutdown=1
opcache.save_comments=1
opcache.load_comments=1
opcache.verbosity_level=2
; opcache.revalidate_freq=60
Opcache ve výsledku udělala brutální rozdíl pro filesytem i redis, takže pro úplnost - tohle nastavení jsem použil
Cache: rychlost
Filesystem (SSD disk!)
První pageload 2607 calls / 452.5 ms / 0.17 ms
Obyčejný pageload 188 calls / 26.8 ms / 0.14 ms
Redis
První pageload 2607 calls / 776.9 ms / 0.30 ms
Obyčejný pageload 188 calls / 44.4 ms / 0.23 ms
První načtení stránky generovalo hromadu cache a tedy i hromadu požadavků na Redis. Ovšem toto nejsou požadavky na Redis, to jsou jednotlivá volání
metod storage, celkový čas strávený jejich voláním a průměr na jeden method call.
Cache: jaktože je pomalejší?!
- redis neumí zámky jako fs
- zápis storage dělá více requestů
- journál dělá více requestů
Jsem stejně v šoku jako vy :) Jenže ono to není tak úplně jednoduché. Zaprvé, časy z předchozího slajdu jsou pro jeden jediný request na localhostu a tedy to
není úplně vypovídající. Filesystem totiž neškáluje zdaleka tak dobře jako Redis a s nárůstem zátěže se rychlost strovná a Redis postupně získá náskok,
protože ten s množstvím requestů téměř vůbec nezpomaluje a horní limit je někde kolem půl milionu GETů za vteřinu.
Redis neumí zamykat a tedy musím zámky emulovat. Emulování zámků se dělá pomocí http://redis.io/commands/setnx a lepší řešení jsem ani po hodinách
studia nenašel. Když se zapisuje do storage, musí se tedy nejdříve získat zámek, potom se zapíše a ještě když ukládáme nějaké tagy ke klíčům tak to dělá
další requesty kvůli journalu. Strávili jsme s @matej_21 několik bezesných nocí optimalizací journalu i storage až na dřeň plošných obvodů a pokud si myslíte
že to zvládnete lépe, budu strašně rád když se zapojíte.
Cache: na produkci
18 ms / rq
Newrelic nám tvrdí že těch ~ 200 požadavů na Redis (tohle je jiné číslo než počet method calls storage) trvá průměrně 18ms na http request. Not bad huh?
Cache: na produkci
FS cacheRedis Redis
Zkoušel jsem Redis storage vypnout, ale bohužel v nočních hodninách už je ten rozdíl neznatelný. V poledne bych si naopak něco takového nedovolil.
Cache: jak probíhá zápis
- získám zámek (loop (setnx;usleep))
- zapíšu
- uvolním zámek
Zápis do cache funguje tak, že nejprve získám zámek cyklickým voláním SETNX na klíč se suffixem ‘:lock’ oproti klíči který chci zamknout. Platnost zámku jde
samozřejmě nastavit na libovolný počet vteřin. Následně zapíšu data a zámek uvolním.
Journál: jak probíhá zápis
- smažu předcházející data pro klíč
- zapíšu (rq ~= klíče*tagy + priorita)
- uvolním zámek
Do journalu se zapisuje trošku složitěji. Nejprve musíme smazat stará data pro daný klíč, tedy odmazat tagy a následně z tagů odmazat klíč, případně ještě
další request na priority. Potom to samé udělám naopak, tedy spáruji jednotlivé tagy s klíčem a klíč s tagy, případně zapíšu prioritu.
Journál: jak to dělá filejournal?
- zamkne journal
- celý journal načte do paměti
- změní co potřebuje
- zapíše journal
Oproti tomu filejournal zamkne celý soubor ve kterém jsou všechna metadata, načte ho do paměti, pomění co potřebuje a opět zapíše. Jinak to totiž udělat ani
nejde, pokud chceme mít atomický zápis. Tento způsob je samozřejmě skvělý, ale pouze do určitého počtu http požadavků.
Journál: jak to dělá filejournal?
- FileJournal::NODE_SIZE
- není možné mít pro jeden klíč víc než
X tagů a pro jeden tag víc než X klíčů
Bohužel tady narážíme na limity filejournalu, tedy že se skládá z jakýchsi datových bloků, do kterých se ukládají data a byť je rozumně naddimenzovaný, i tak
se může stát že máte moc tagů pro nějaký klíč, nebo moc klíčů pro nějaký tag a zkrátka nebude možné data uložit. Redis journal je omezen pouze velikostí
ramky.
Cache: smazání klíče
- smaže klíče
Tady je to naštěstí velice jednoduché, stačí jeden request a data jsou fuč :)
Cache: expirace klíče
Filestorage ho musí načíst,
ověřit a “ručně” smazat.
V Redisu automaticky expiruje,
jako by tam nikdy nebyl :)
Další skvělá feature redis cache storage je automatická expirace klíčů na úrovni databáze. Filestorage je po sobě musí klízet když zjistí že data mají expirovat,
v Redisu prostě zmizí.
Cache: mazání podle tagu
- získá seznam klíčů pro tag (journal)
- smazat tagy z klíčů (journal)
- smazat klíče z tagů (journal)
- vrátí seznam klíčů na smazání
- smazat nalezené klíče (cache)
Tohle je asi největší špek jaký jsme v celém journalu řešili. Normální filestorage a journal fungují tak, že storage dá journalu tag (případně jiné pravidlo jak
cache mazat) a zeptá se jaké klíče ten tag mají a které teda má mazat. Journal to přechroustá a vrátí list klíčů. Cache následně maže data.
Cache: mazání podle tagu
počet requestů odpovídá velikosti dat
10 000 rq?
100 000 rq?
1 000 000 rq?
Co byste řekli, kolik musí udělat requestů algoritmus popsaný na minulém slide? Pokud byste se nebáli tipnout i ta šílená čísla s hodně nulami nebyli byste
daleko od pravdy, protože pokud máte u jednoho tagu tisíce klíčů cache, může to dát redisu pořádně pokouřit.
Cache: mazání podle tagu
1 request
= eval lua scriptu
Ovšem s tím se odmítám spokojit! Jak jsme si řekli, Redis umí scriptovat v Lua a proto jsem napsal mazání pomocí tagů journalu jako Lua script, který se
jednoduše pošle databázi s argumentem (jméno tagu, priorita), databáze evalne script a ten najde všechny klíče, promaže všechna metadata a pokud
použiváte redis cache storage i journal zároveň, rovnou zkusí klíče z databáze smazat. Ušetří se tedy vracení seznamu klíčů a mazání “z venku”.
Optimalizace
- ještě rychlejší Redis!
Optimalizace: unixové sockety
“The typical latency of a 1 GBits/s
network is about 200 us, while the
latency with a Unix domain socket can
be as low as 30 us.”
Lokální síť mezi dvěma VPS je samozřejmě brutálně rychlá a když posíláte jenom pár requestů tak ten rozdíl nejspíš nepocítíte, ale když sypete do Redisu na
každý http request stovky příkazů tak už se vyplatí zamyslet se nad použitím lokálních instací redisu na cachování pro každý http server (myslím tím VPS, která
je určená ke zpracování http requestů a běží na ní PHP).
Optimalizace
- zvlášť instance na session a na cache
- vypnout serializaci cache na disk
- vypnout zamykání cache pro zápis
Kdyby/Redis je sice chytrý a cache i session prefixuje a tedy se nikdy nepomýchají, ale výborné je rozdělit je do dvou různých databází. Jak jsme si řekli, data v
redisu se mohou dělit na databáze a tedy při deployi můžete jednoduše zavolat `redis-cli -n 0 flushdb` a smazat tak databázi s cachí a session zůstane
nedotčena.
Pokud to chcete povýšit, místo použití databází můžete nastartovat dvě různé instance redisu a jednu použít na session a jednu na cache. Díky tomu budete
moci vypnout ukládání cache na disk a tedy zase trochu ulehčíte Redisu ve špičkách.
Když jsme měli problémy s výkonem, protože jsme hodně experimentovali, zkoušeli jsme i vypnout zamykání cache pro write, ale výsledkem bylo jenom to, že
se cache generovala klidně 100x dokud ji ten první request, co ji generovat začal, konečně nezapsal a tedy se výkon logicky zhoršil.
Optimalizace: cache nestíhá :(
Vypnutí generování cache, nebo naopak když generujete cache strašně moc v jeden moment může vypadat i takto. Naprostá většina toho nárustu je
spůsobená sleepy v cyklech a opakovné dotazování Redisu jestli už se zámek uvolnil. Stroj tedy ve skutečnosti není zase o tolik vytíženější, jenom mu déle
trvá zpracovat http requesty.
Sharding - moar servers!!
Optimalizace: sharding
Více instancí => více vláken!
+ persistentní spojení
No a když už vám návštěvnost naroste takovým způsobem že už nic nepomáhá a komunikace s Redisem se ukáže jako úzké hrdlo, je na řadě zvážit sharding.
Protože jak jsme si řekli na začátku, Redis je jednovláknový a tedy tím že nastartujete více instancí (třeb 16, nebo klidně 64) získáte více vláken :)
Optimalizace: sharding
- https://github.com/twitter/twemproxy
- kdyby/redis (maybe?)
Asi nejpoužívanější nástroj na shardování Redisu je twemproxy od Twitteru, jenže ta je navržená tak, že by asi úplně dobře nefungovala při invalidaci cache
pomocí našeho LUA scriptu, tedy tu bohužel nemůžu pro kombinaci s Kdyby/Redis doporučit.
Ale nenechám vás na holičkách, mám napsané vlastní klientské shardování. Zatím ovšem není v masteru, ale v samostatné větvi a budu rád když ji se mnou
zkusíte otestovat, ale opatrně! :)
A závěr?
A vyplatí se teda (Kdyby/)Redis?
Jak jsme si ukázali, naše konkrétní implementace storage umí bohužel i nemile překvapit.
Vyplatí se pro
Session: vždy
Journal: vždy
Ovšem i kdyby byla klidně ještě o polovinu pomalejší, pořád se ve 100% případů vyplatí použít pro session.
A pokud tagujete cache tak v ten moment se journal a cache vyplatí i vám.
Dotazy?
Díky za pozornost!

Mais conteúdo relacionado

Mais procurados

CRCE - přehled datového modelu a vybraná API
CRCE - přehled datového modelu a vybraná APICRCE - přehled datového modelu a vybraná API
CRCE - přehled datového modelu a vybraná APIPremek Brada
 
Aplikační nastavení v .NET
Aplikační nastavení v .NETAplikační nastavení v .NET
Aplikační nastavení v .NETJan Hřídel
 
Webinář: Oracle DBA - RAC - Úvod do problematiky
Webinář: Oracle DBA - RAC - Úvod do problematikyWebinář: Oracle DBA - RAC - Úvod do problematiky
Webinář: Oracle DBA - RAC - Úvod do problematikyTomas Solar
 
INPTP Rekapitulace
INPTP Rekapitulace INPTP Rekapitulace
INPTP Rekapitulace Jan Hřídel
 
Oracle RMAN - nastavení a provedení zálohy
Oracle RMAN - nastavení a provedení zálohyOracle RMAN - nastavení a provedení zálohy
Oracle RMAN - nastavení a provedení zálohyTomas Solar
 
Architektura databáze Oracle
Architektura databáze OracleArchitektura databáze Oracle
Architektura databáze OracleTomas Solar
 
Instalace databáze Oracle 12.1.0.2.0 na Oracle Enterprise linux 7.0 (OEL70)
Instalace databáze Oracle 12.1.0.2.0 na Oracle Enterprise linux 7.0 (OEL70)Instalace databáze Oracle 12.1.0.2.0 na Oracle Enterprise linux 7.0 (OEL70)
Instalace databáze Oracle 12.1.0.2.0 na Oracle Enterprise linux 7.0 (OEL70)Tomas Solar
 
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)Martin Zeman
 
Vývoj aplikací pro iOS
Vývoj aplikací pro iOSVývoj aplikací pro iOS
Vývoj aplikací pro iOSPetr Dvorak
 

Mais procurados (13)

Kdyby/Events #posobota
Kdyby/Events #posobotaKdyby/Events #posobota
Kdyby/Events #posobota
 
CRCE - přehled datového modelu a vybraná API
CRCE - přehled datového modelu a vybraná APICRCE - přehled datového modelu a vybraná API
CRCE - přehled datového modelu a vybraná API
 
Aplikační nastavení v .NET
Aplikační nastavení v .NETAplikační nastavení v .NET
Aplikační nastavení v .NET
 
Clean code
Clean codeClean code
Clean code
 
Kurz linux 1 pub
Kurz linux 1   pubKurz linux 1   pub
Kurz linux 1 pub
 
Webinář: Oracle DBA - RAC - Úvod do problematiky
Webinář: Oracle DBA - RAC - Úvod do problematikyWebinář: Oracle DBA - RAC - Úvod do problematiky
Webinář: Oracle DBA - RAC - Úvod do problematiky
 
INPTP Rekapitulace
INPTP Rekapitulace INPTP Rekapitulace
INPTP Rekapitulace
 
Oracle RMAN - nastavení a provedení zálohy
Oracle RMAN - nastavení a provedení zálohyOracle RMAN - nastavení a provedení zálohy
Oracle RMAN - nastavení a provedení zálohy
 
Architektura databáze Oracle
Architektura databáze OracleArchitektura databáze Oracle
Architektura databáze Oracle
 
Instalace databáze Oracle 12.1.0.2.0 na Oracle Enterprise linux 7.0 (OEL70)
Instalace databáze Oracle 12.1.0.2.0 na Oracle Enterprise linux 7.0 (OEL70)Instalace databáze Oracle 12.1.0.2.0 na Oracle Enterprise linux 7.0 (OEL70)
Instalace databáze Oracle 12.1.0.2.0 na Oracle Enterprise linux 7.0 (OEL70)
 
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
MicroKernel - aneb špatný název pro Helper (5. sraz přátel Symfony v Praze)
 
PZ2021
PZ2021PZ2021
PZ2021
 
Vývoj aplikací pro iOS
Vývoj aplikací pro iOSVývoj aplikací pro iOS
Vývoj aplikací pro iOS
 

Semelhante a Kdyby/Redis

RocDevs/PHPPrague - Proč by sakra někdo měl chtít dělat eshop?
RocDevs/PHPPrague - Proč by sakra někdo měl chtít dělat eshop?RocDevs/PHPPrague - Proč by sakra někdo měl chtít dělat eshop?
RocDevs/PHPPrague - Proč by sakra někdo měl chtít dělat eshop?Tomáš Strejček
 
node.js: zápisky z fronty (Battle guide to node.js)
node.js: zápisky z fronty (Battle guide to node.js)node.js: zápisky z fronty (Battle guide to node.js)
node.js: zápisky z fronty (Battle guide to node.js)almadcz
 
Škálování, optimalizaci a zálohování databáze MySQL
Škálování, optimalizaci a zálohování databáze MySQLŠkálování, optimalizaci a zálohování databáze MySQL
Škálování, optimalizaci a zálohování databáze MySQLJakub Vrána
 
4311 souborovy system_os_net_ware_1
4311 souborovy system_os_net_ware_14311 souborovy system_os_net_ware_1
4311 souborovy system_os_net_ware_1pisaceku
 
Relační databáze efektivně z pohledu vývojáře
Relační databáze efektivně z pohledu vývojářeRelační databáze efektivně z pohledu vývojáře
Relační databáze efektivně z pohledu vývojářeJan Smitka
 
Revoluce v cloudu: první autonomně řízená databáze na světě
Revoluce v cloudu: první autonomně řízená databáze na světěRevoluce v cloudu: první autonomně řízená databáze na světě
Revoluce v cloudu: první autonomně řízená databáze na světěMarketingArrowECS_CZ
 
PHP Vysočina - WordPress - 25.10.2018
PHP Vysočina - WordPress - 25.10.2018PHP Vysočina - WordPress - 25.10.2018
PHP Vysočina - WordPress - 25.10.2018Brilo Team
 
AWS spot instances
AWS spot instancesAWS spot instances
AWS spot instancesCollabim
 
Postgresql na EXT3/4, XFS, BTRFS a ZFS
Postgresql na EXT3/4, XFS, BTRFS a ZFSPostgresql na EXT3/4, XFS, BTRFS a ZFS
Postgresql na EXT3/4, XFS, BTRFS a ZFSTomas Vondra
 
WordCamp Brno 2017 - rychlý a bezpečný web
WordCamp Brno 2017  - rychlý a bezpečný webWordCamp Brno 2017  - rychlý a bezpečný web
WordCamp Brno 2017 - rychlý a bezpečný webVladimír Smitka
 
Petr Joachim: Redis na Super.cz
Petr Joachim: Redis na Super.czPetr Joachim: Redis na Super.cz
Petr Joachim: Redis na Super.czJano Suchal
 
Optimalizace Symfony na devu
 Optimalizace Symfony na devu Optimalizace Symfony na devu
Optimalizace Symfony na devuVašek Purchart
 
Vašek Purchart - Optimalizace Symfony na devu (2. sraz přátel Symfony v Praze)
Vašek Purchart - Optimalizace Symfony na devu (2. sraz přátel Symfony v Praze)Vašek Purchart - Optimalizace Symfony na devu (2. sraz přátel Symfony v Praze)
Vašek Purchart - Optimalizace Symfony na devu (2. sraz přátel Symfony v Praze)Péhápkaři
 
Český fulltext a sdílené slovníky
Český fulltext a sdílené slovníkyČeský fulltext a sdílené slovníky
Český fulltext a sdílené slovníkyTomas Vondra
 
Výkonnost webových aplikací
Výkonnost webových aplikacíVýkonnost webových aplikací
Výkonnost webových aplikacíTaste Medio
 
Jak zrychlit WP pomocí cachovacích pluginů
Jak zrychlit WP pomocí cachovacích pluginůJak zrychlit WP pomocí cachovacích pluginů
Jak zrychlit WP pomocí cachovacích pluginůJakub Klapka
 

Semelhante a Kdyby/Redis (20)

RocDevs/PHPPrague - Proč by sakra někdo měl chtít dělat eshop?
RocDevs/PHPPrague - Proč by sakra někdo měl chtít dělat eshop?RocDevs/PHPPrague - Proč by sakra někdo měl chtít dělat eshop?
RocDevs/PHPPrague - Proč by sakra někdo měl chtít dělat eshop?
 
Daos
DaosDaos
Daos
 
node.js: zápisky z fronty (Battle guide to node.js)
node.js: zápisky z fronty (Battle guide to node.js)node.js: zápisky z fronty (Battle guide to node.js)
node.js: zápisky z fronty (Battle guide to node.js)
 
Škálování, optimalizaci a zálohování databáze MySQL
Škálování, optimalizaci a zálohování databáze MySQLŠkálování, optimalizaci a zálohování databáze MySQL
Škálování, optimalizaci a zálohování databáze MySQL
 
4311 souborovy system_os_net_ware_1
4311 souborovy system_os_net_ware_14311 souborovy system_os_net_ware_1
4311 souborovy system_os_net_ware_1
 
Relační databáze efektivně z pohledu vývojáře
Relační databáze efektivně z pohledu vývojářeRelační databáze efektivně z pohledu vývojáře
Relační databáze efektivně z pohledu vývojáře
 
Revoluce v cloudu: první autonomně řízená databáze na světě
Revoluce v cloudu: první autonomně řízená databáze na světěRevoluce v cloudu: první autonomně řízená databáze na světě
Revoluce v cloudu: první autonomně řízená databáze na světě
 
Red Hat Storage Server presentation
Red Hat Storage Server presentationRed Hat Storage Server presentation
Red Hat Storage Server presentation
 
PHP Vysočina - WordPress - 25.10.2018
PHP Vysočina - WordPress - 25.10.2018PHP Vysočina - WordPress - 25.10.2018
PHP Vysočina - WordPress - 25.10.2018
 
AWS spot instances
AWS spot instancesAWS spot instances
AWS spot instances
 
Postgresql na EXT3/4, XFS, BTRFS a ZFS
Postgresql na EXT3/4, XFS, BTRFS a ZFSPostgresql na EXT3/4, XFS, BTRFS a ZFS
Postgresql na EXT3/4, XFS, BTRFS a ZFS
 
WordCamp Brno 2017 - rychlý a bezpečný web
WordCamp Brno 2017  - rychlý a bezpečný webWordCamp Brno 2017  - rychlý a bezpečný web
WordCamp Brno 2017 - rychlý a bezpečný web
 
Petr Joachim: Redis na Super.cz
Petr Joachim: Redis na Super.czPetr Joachim: Redis na Super.cz
Petr Joachim: Redis na Super.cz
 
Optimalizace Symfony na devu
 Optimalizace Symfony na devu Optimalizace Symfony na devu
Optimalizace Symfony na devu
 
Vašek Purchart - Optimalizace Symfony na devu (2. sraz přátel Symfony v Praze)
Vašek Purchart - Optimalizace Symfony na devu (2. sraz přátel Symfony v Praze)Vašek Purchart - Optimalizace Symfony na devu (2. sraz přátel Symfony v Praze)
Vašek Purchart - Optimalizace Symfony na devu (2. sraz přátel Symfony v Praze)
 
Český fulltext a sdílené slovníky
Český fulltext a sdílené slovníkyČeský fulltext a sdílené slovníky
Český fulltext a sdílené slovníky
 
Výkonnost webových aplikací
Výkonnost webových aplikacíVýkonnost webových aplikací
Výkonnost webových aplikací
 
Jak zrychlit WP pomocí cachovacích pluginů
Jak zrychlit WP pomocí cachovacích pluginůJak zrychlit WP pomocí cachovacích pluginů
Jak zrychlit WP pomocí cachovacích pluginů
 
Instalace WordPress
Instalace WordPressInstalace WordPress
Instalace WordPress
 
Možnosti databázové komprese
Možnosti databázové kompreseMožnosti databázové komprese
Možnosti databázové komprese
 

Mais de Filip Procházka

Mais de Filip Procházka (8)

4 roky remote
4 roky remote4 roky remote
4 roky remote
 
Před čím vás Nette ani Symfony neochrání
Před čím vás Nette ani Symfony neochráníPřed čím vás Nette ani Symfony neochrání
Před čím vás Nette ani Symfony neochrání
 
Nejlepší cache je žádná cache
Nejlepší cache je žádná cacheNejlepší cache je žádná cache
Nejlepší cache je žádná cache
 
Testování prakticky
Testování praktickyTestování prakticky
Testování prakticky
 
Kdyby/Translation
Kdyby/TranslationKdyby/Translation
Kdyby/Translation
 
Kdyby/Events
Kdyby/EventsKdyby/Events
Kdyby/Events
 
Nette Tester / Posobota
Nette Tester / PosobotaNette Tester / Posobota
Nette Tester / Posobota
 
Composer / Posobota
Composer / PosobotaComposer / Posobota
Composer / Posobota
 

Kdyby/Redis

  • 2. Jaký je plán? - řekneme si co je Redis - co umí kdyby/redis - zprovozníme ho - profit
  • 3. Co je Redis? - nízkoúrovňová databáze - s datovými strukturami - se scriptováním v LUA - serializuje se na disk - jednovláknový Redis umí datové struktury od jednoduchých key:value, přes seznamy a hashe po seřazené sety. Je možné mu poslat script v LUA který evalne přímo nad databázi, tedy si ušetříte hromadu komunikace. Další killer feature oproti memcache je i serializace na disk, což z něj dělá perfektního kanditáta pro session.
  • 4. .. a umí ještě - databáze (forma namespace) - transakce (optimistic locking) - pub/sub - replikace
  • 5. .. a hlavně Je ve všem stejně rychlý nebo rychlejší než memcached
  • 6. První dva bottlenecky v Nette? session a journal Výchozí session file storage je super, ale od určité návštěvnostni zvládá s přehledem zabíjet stránku. Journal v Nette je velice jednoduchá databáze, do které se ukládá jaké mají data v cachi tagy a priority pro mazání. Journal není tak úplně bottleneck pokud nepoužíváte tagy, ovšem pokud je používáte, tak narazíte na problémy při větší zátěži, nebo když do něj chce zapisovat hodně dat.
  • 7. Na co je Redis super? - session - cache - je to přece databáze! Redis se dá použít nejenom na cachování a sessions, ale je to i plnohodnotná databáze a tedy do ní můžete přešunout i jiné části aplikace a zefektivnit ji tím.
  • 8. Instalace: Redis Redis: http://redis.io/download PHP Extension: http://pecl.php.net/package/redis Je potřeba nainstalovat nejenom samotnou databázi Redis, ale taky i PHP extension, abychom z rychlosti vytřískali maximum.
  • 9. Instalace: Kdyby/Redis $ composer require kdyby/redis:~3.0 app/config/config.neon extensions: redis: KdybyRedisDIRedisExtension Samozřejmostí je instalace Kdyby/Redis přes composer a compiler extension. Řada 3.0 je pro Nette 2.1 a dev.
  • 11. Session Výchozí PHP session storage stojí za úplný ho... uby! Největší dvě úzká hrdla jsou čištění starých session a limit počtu souborů na složku ve většine filesystémů. Obojí jde řešit, ale přoč tím ztrácet čas když máme možnost použít Redis.
  • 12. Session: nativní storage session.save_handler = redis session.save_path = "tcp://127.0.0.1:6379" zapíná se pomocí: redis: session: on Nativní storage využívá interního mechanismu v PHP na ukládání session a handleru který dodává phpredis (ten php extension). Důležité ovšem je, že tato forma ukládání session neblokuje a možná ani nikdy nebude, protože Redis sám o sobě nepodporuje zamykání.
  • 13. Session: emulovaný storage SessionHandlerInterface zapíná se pomocí: redis: session: {native: off} Kdyby/Redis ale obsahuje i vlastní implementaci, která využívá jiný PHP mechanismus na ukládání sessions. Proč psát vlastní? Protože tato implementace dokáže session zamykat, jako standardní filesystemová. Díky tomu se nám nebudou přepisovat a ztrácet data. Obě implementace jsou kompatibilní a lze je libovolně přepínat bez strachu ze ztráty dat.
  • 15. Cache: CachingIStorage redis: storage: on journal: on Kdyby/Redis obsahuje oddělené implementace journalu a cache a je možné obě dvě používat samostatně, ale ve výsledku dává smysl hlavně použití obou zároveň.
  • 16. Cache: rychlost class BenchmarkFileStorage implements NetteCachingIStorage { function __construct(NetteCachingIStorage $storage); function read($key) { try { $time = microtime(TRUE); return $this->storage->read($key); } finally {$this->calls[]=microtime(TRUE)-$time;} } Večer před posobotou jsem se rozhodl změřit rozdíl rychlosti FS storage oproti Redisu abych mohl ohromit slečny v publiku a napsal jsem si vlastní storage dekorátor, kterým jsem plánoval měřit dobu strávenou v cachi.
  • 18. Cache: rychlost Filesystem (SSD disk!) První pageload 2607 calls / 452.5 ms / 0.17 ms Obyčejný pageload 188 calls / 26.8 ms / 0.14 ms Redis První pageload 2607 calls / 776.9 ms / 0.30 ms Obyčejný pageload 188 calls / 44.4 ms / 0.23 ms První načtení stránky generovalo hromadu cache a tedy i hromadu požadavků na Redis. Ovšem toto nejsou požadavky na Redis, to jsou jednotlivá volání metod storage, celkový čas strávený jejich voláním a průměr na jeden method call.
  • 19. Cache: jaktože je pomalejší?! - redis neumí zámky jako fs - zápis storage dělá více requestů - journál dělá více requestů Jsem stejně v šoku jako vy :) Jenže ono to není tak úplně jednoduché. Zaprvé, časy z předchozího slajdu jsou pro jeden jediný request na localhostu a tedy to není úplně vypovídající. Filesystem totiž neškáluje zdaleka tak dobře jako Redis a s nárůstem zátěže se rychlost strovná a Redis postupně získá náskok, protože ten s množstvím requestů téměř vůbec nezpomaluje a horní limit je někde kolem půl milionu GETů za vteřinu. Redis neumí zamykat a tedy musím zámky emulovat. Emulování zámků se dělá pomocí http://redis.io/commands/setnx a lepší řešení jsem ani po hodinách studia nenašel. Když se zapisuje do storage, musí se tedy nejdříve získat zámek, potom se zapíše a ještě když ukládáme nějaké tagy ke klíčům tak to dělá další requesty kvůli journalu. Strávili jsme s @matej_21 několik bezesných nocí optimalizací journalu i storage až na dřeň plošných obvodů a pokud si myslíte že to zvládnete lépe, budu strašně rád když se zapojíte.
  • 20. Cache: na produkci 18 ms / rq Newrelic nám tvrdí že těch ~ 200 požadavů na Redis (tohle je jiné číslo než počet method calls storage) trvá průměrně 18ms na http request. Not bad huh?
  • 21. Cache: na produkci FS cacheRedis Redis Zkoušel jsem Redis storage vypnout, ale bohužel v nočních hodninách už je ten rozdíl neznatelný. V poledne bych si naopak něco takového nedovolil.
  • 22. Cache: jak probíhá zápis - získám zámek (loop (setnx;usleep)) - zapíšu - uvolním zámek Zápis do cache funguje tak, že nejprve získám zámek cyklickým voláním SETNX na klíč se suffixem ‘:lock’ oproti klíči který chci zamknout. Platnost zámku jde samozřejmě nastavit na libovolný počet vteřin. Následně zapíšu data a zámek uvolním.
  • 23. Journál: jak probíhá zápis - smažu předcházející data pro klíč - zapíšu (rq ~= klíče*tagy + priorita) - uvolním zámek Do journalu se zapisuje trošku složitěji. Nejprve musíme smazat stará data pro daný klíč, tedy odmazat tagy a následně z tagů odmazat klíč, případně ještě další request na priority. Potom to samé udělám naopak, tedy spáruji jednotlivé tagy s klíčem a klíč s tagy, případně zapíšu prioritu.
  • 24. Journál: jak to dělá filejournal? - zamkne journal - celý journal načte do paměti - změní co potřebuje - zapíše journal Oproti tomu filejournal zamkne celý soubor ve kterém jsou všechna metadata, načte ho do paměti, pomění co potřebuje a opět zapíše. Jinak to totiž udělat ani nejde, pokud chceme mít atomický zápis. Tento způsob je samozřejmě skvělý, ale pouze do určitého počtu http požadavků.
  • 25. Journál: jak to dělá filejournal? - FileJournal::NODE_SIZE - není možné mít pro jeden klíč víc než X tagů a pro jeden tag víc než X klíčů Bohužel tady narážíme na limity filejournalu, tedy že se skládá z jakýchsi datových bloků, do kterých se ukládají data a byť je rozumně naddimenzovaný, i tak se může stát že máte moc tagů pro nějaký klíč, nebo moc klíčů pro nějaký tag a zkrátka nebude možné data uložit. Redis journal je omezen pouze velikostí ramky.
  • 26. Cache: smazání klíče - smaže klíče Tady je to naštěstí velice jednoduché, stačí jeden request a data jsou fuč :)
  • 27. Cache: expirace klíče Filestorage ho musí načíst, ověřit a “ručně” smazat. V Redisu automaticky expiruje, jako by tam nikdy nebyl :) Další skvělá feature redis cache storage je automatická expirace klíčů na úrovni databáze. Filestorage je po sobě musí klízet když zjistí že data mají expirovat, v Redisu prostě zmizí.
  • 28. Cache: mazání podle tagu - získá seznam klíčů pro tag (journal) - smazat tagy z klíčů (journal) - smazat klíče z tagů (journal) - vrátí seznam klíčů na smazání - smazat nalezené klíče (cache) Tohle je asi největší špek jaký jsme v celém journalu řešili. Normální filestorage a journal fungují tak, že storage dá journalu tag (případně jiné pravidlo jak cache mazat) a zeptá se jaké klíče ten tag mají a které teda má mazat. Journal to přechroustá a vrátí list klíčů. Cache následně maže data.
  • 29. Cache: mazání podle tagu počet requestů odpovídá velikosti dat 10 000 rq? 100 000 rq? 1 000 000 rq? Co byste řekli, kolik musí udělat requestů algoritmus popsaný na minulém slide? Pokud byste se nebáli tipnout i ta šílená čísla s hodně nulami nebyli byste daleko od pravdy, protože pokud máte u jednoho tagu tisíce klíčů cache, může to dát redisu pořádně pokouřit.
  • 30. Cache: mazání podle tagu 1 request = eval lua scriptu Ovšem s tím se odmítám spokojit! Jak jsme si řekli, Redis umí scriptovat v Lua a proto jsem napsal mazání pomocí tagů journalu jako Lua script, který se jednoduše pošle databázi s argumentem (jméno tagu, priorita), databáze evalne script a ten najde všechny klíče, promaže všechna metadata a pokud použiváte redis cache storage i journal zároveň, rovnou zkusí klíče z databáze smazat. Ušetří se tedy vracení seznamu klíčů a mazání “z venku”.
  • 32. Optimalizace: unixové sockety “The typical latency of a 1 GBits/s network is about 200 us, while the latency with a Unix domain socket can be as low as 30 us.” Lokální síť mezi dvěma VPS je samozřejmě brutálně rychlá a když posíláte jenom pár requestů tak ten rozdíl nejspíš nepocítíte, ale když sypete do Redisu na každý http request stovky příkazů tak už se vyplatí zamyslet se nad použitím lokálních instací redisu na cachování pro každý http server (myslím tím VPS, která je určená ke zpracování http requestů a běží na ní PHP).
  • 33. Optimalizace - zvlášť instance na session a na cache - vypnout serializaci cache na disk - vypnout zamykání cache pro zápis Kdyby/Redis je sice chytrý a cache i session prefixuje a tedy se nikdy nepomýchají, ale výborné je rozdělit je do dvou různých databází. Jak jsme si řekli, data v redisu se mohou dělit na databáze a tedy při deployi můžete jednoduše zavolat `redis-cli -n 0 flushdb` a smazat tak databázi s cachí a session zůstane nedotčena. Pokud to chcete povýšit, místo použití databází můžete nastartovat dvě různé instance redisu a jednu použít na session a jednu na cache. Díky tomu budete moci vypnout ukládání cache na disk a tedy zase trochu ulehčíte Redisu ve špičkách. Když jsme měli problémy s výkonem, protože jsme hodně experimentovali, zkoušeli jsme i vypnout zamykání cache pro write, ale výsledkem bylo jenom to, že se cache generovala klidně 100x dokud ji ten první request, co ji generovat začal, konečně nezapsal a tedy se výkon logicky zhoršil.
  • 34. Optimalizace: cache nestíhá :( Vypnutí generování cache, nebo naopak když generujete cache strašně moc v jeden moment může vypadat i takto. Naprostá většina toho nárustu je spůsobená sleepy v cyklech a opakovné dotazování Redisu jestli už se zámek uvolnil. Stroj tedy ve skutečnosti není zase o tolik vytíženější, jenom mu déle trvá zpracovat http requesty.
  • 35. Sharding - moar servers!!
  • 36. Optimalizace: sharding Více instancí => více vláken! + persistentní spojení No a když už vám návštěvnost naroste takovým způsobem že už nic nepomáhá a komunikace s Redisem se ukáže jako úzké hrdlo, je na řadě zvážit sharding. Protože jak jsme si řekli na začátku, Redis je jednovláknový a tedy tím že nastartujete více instancí (třeb 16, nebo klidně 64) získáte více vláken :)
  • 37. Optimalizace: sharding - https://github.com/twitter/twemproxy - kdyby/redis (maybe?) Asi nejpoužívanější nástroj na shardování Redisu je twemproxy od Twitteru, jenže ta je navržená tak, že by asi úplně dobře nefungovala při invalidaci cache pomocí našeho LUA scriptu, tedy tu bohužel nemůžu pro kombinaci s Kdyby/Redis doporučit. Ale nenechám vás na holičkách, mám napsané vlastní klientské shardování. Zatím ovšem není v masteru, ale v samostatné větvi a budu rád když ji se mnou zkusíte otestovat, ale opatrně! :)
  • 38. A závěr? A vyplatí se teda (Kdyby/)Redis? Jak jsme si ukázali, naše konkrétní implementace storage umí bohužel i nemile překvapit.
  • 39. Vyplatí se pro Session: vždy Journal: vždy Ovšem i kdyby byla klidně ještě o polovinu pomalejší, pořád se ve 100% případů vyplatí použít pro session. A pokud tagujete cache tak v ten moment se journal a cache vyplatí i vám.