{"id":1358,"date":"2026-04-08T12:57:31","date_gmt":"2026-04-08T10:57:31","guid":{"rendered":"https:\/\/trzykody.pl\/?p=1358"},"modified":"2026-04-20T13:01:24","modified_gmt":"2026-04-20T11:01:24","slug":"cache-wynikow","status":"publish","type":"post","link":"https:\/\/trzykody.pl\/index.php\/2026\/04\/08\/cache-wynikow\/","title":{"rendered":"Cache wynik\u00f3w"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Systemy informatyczne bardzo rzadko przegrywaj\u0105 przez brak funkcjonalno\u015bci. Znacznie cz\u0119\u015bciej problemem jest czas odpowiedzi, nadmierne obci\u0105\u017cenie bazy danych, zbyt du\u017ca liczba zapyta\u0144 do API albo niepotrzebne przeliczanie tych samych danych setki razy na minut\u0119. U\u017cytkownik nie widzi wtedy algorytm\u00f3w ani architektury &#8211; widzi tylko woln\u0105 stron\u0119, zawieszaj\u0105cy si\u0119 panel albo raport generuj\u0105cy si\u0119 przez kilka minut. Jednym z najprostszych i jednocze\u015bnie najskuteczniejszych sposob\u00f3w ograniczenia tego problemu jest <strong>Cache wynik\u00f3w<\/strong>.<\/p>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Spis Tre\u015bci<\/h2><nav><ol><li><a href=\"#cache-wynikow-jako-mechanizm-ograniczania-kosztu-wielokrotnego-wykonywania-tych-samych-operacji\">Cache wynik\u00f3w jako mechanizm ograniczania kosztu wielokrotnego wykonywania tych samych operacji<\/a><ol><li><a href=\"#podstawowy-wzor-opisujacy-oplacalnosc-stosowania-pamieci-podrecznej\">Podstawowy wz\u00f3r opisuj\u0105cy op\u0142acalno\u015b\u0107 stosowania pami\u0119ci podr\u0119cznej<\/a><\/li><\/ol><\/li><li><a href=\"#cache-wynikow-w-bazach-danych-api-i-aplikacjach-webowych-dziala-inaczej-niz-wielu-poczatkujacych-zaklada\">Cache wynik\u00f3w w bazach danych, API i aplikacjach webowych dzia\u0142a inaczej ni\u017c wielu pocz\u0105tkuj\u0105cych zak\u0142ada<\/a><ol><li><a href=\"#cache-zapytan-do-bazy-danych\">Cache zapyta\u0144 do bazy danych<\/a><\/li><li><a href=\"#przyklad-w-python\">Przyk\u0142ad w Python<\/a><\/li><li><a href=\"#przyklad-w-c\">Przyk\u0142ad w C<\/a><\/li><li><a href=\"#przyklad-w-c-1\">Przyk\u0142ad w C++<\/a><\/li><li><a href=\"#przyklad-w-php\">Przyk\u0142ad w PHP<\/a><\/li><li><a href=\"#cache-odpowiedzi-api\">Cache odpowiedzi API<\/a><\/li><\/ol><\/li><li><a href=\"#cache-wynikow-wymaga-poprawnego-uniewazniania-danych-bo-tu-najczesciej-powstaja-realne-problemy-produkcyjne\">Cache wynik\u00f3w wymaga poprawnego uniewa\u017cniania danych bo tu najcz\u0119\u015bciej powstaj\u0105 realne problemy produkcyjne<\/a><ol><li><a href=\"#najczestsze-strategie-wygaszania-cache\">Najcz\u0119stsze strategie wygaszania cache<\/a><\/li><li><a href=\"#ttl-time-to-live\">TTL &#8211; Time To Live<\/a><\/li><li><a href=\"#invalidation-po-zmianie-danych\">Invalidation po zmianie danych<\/a><\/li><li><a href=\"#lru-least-recently-used\">LRU &#8211; Least Recently Used<\/a><\/li><li><a href=\"#praktyczny-wzor-na-wspolczynnik-trafien\">Praktyczny wz\u00f3r na wsp\u00f3\u0142czynnik trafie\u0144<\/a><\/li><li><a href=\"#typowe-pulapki\">Typowe pu\u0142apki<\/a><ol><li><a href=\"#cache-wszystkiego\">Cache wszystkiego<\/a><\/li><li><a href=\"#brak-limitu-pamieci\">Brak limitu pami\u0119ci<\/a><\/li><li><a href=\"#brak-monitoringu\">Brak monitoringu<\/a><\/li><li><a href=\"#zbyt-dlugi-ttl\">Zbyt d\u0142ugi TTL<\/a><\/li><li><a href=\"#cache-danych-wrazliwych-bez-kontroli\">Cache danych wra\u017cliwych bez kontroli<\/a><\/li><\/ol><\/li><\/ol><\/li><li><a href=\"#faq\">FAQ<\/a><ol><li><a href=\"#czy-cache-zawsze-przyspiesza-aplikacje\">Czy cache zawsze przyspiesza aplikacj\u0119<\/a><\/li><li><a href=\"#czy-redis-jest-obowiazkowy\">Czy Redis jest obowi\u0105zkowy<\/a><\/li><li><a href=\"#czy-cache-moze-powodowac-bledy-biznesowe\">Czy cache mo\u017ce powodowa\u0107 b\u0142\u0119dy biznesowe<\/a><\/li><li><a href=\"#memoizacja-i-cache-to-to-samo\">Memoizacja i cache to to samo<\/a><\/li><li><a href=\"#kiedy-najlepiej-wdrazac-cache\">Kiedy najlepiej wdra\u017ca\u0107 cache<\/a><\/li><\/ol><\/li><\/ol><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cache-wynikow-jako-mechanizm-ograniczania-kosztu-wielokrotnego-wykonywania-tych-samych-operacji\">Cache wynik\u00f3w jako mechanizm ograniczania kosztu wielokrotnego wykonywania tych samych operacji<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Najprostsza definicja jest praktyczna: je\u017celi program raz obliczy\u0142 wynik i istnieje du\u017ce prawdopodobie\u0144stwo, \u017ce za chwil\u0119 b\u0119dzie potrzebowa\u0142 dok\u0142adnie tego samego rezultatu, warto ten rezultat zachowa\u0107 i u\u017cy\u0107 ponownie zamiast liczy\u0107 od pocz\u0105tku.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To podej\u015bcie dotyczy wielu warstw systemu:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>zapyta\u0144 SQL<\/li>\n\n\n\n<li>wynik\u00f3w funkcji<\/li>\n\n\n\n<li>odpowiedzi z zewn\u0119trznych API<\/li>\n\n\n\n<li>renderowanych fragment\u00f3w HTML<\/li>\n\n\n\n<li>wynik\u00f3w raport\u00f3w<\/li>\n\n\n\n<li>danych sesyjnych<\/li>\n\n\n\n<li>oblicze\u0144 matematycznych<\/li>\n\n\n\n<li>przetworzonych plik\u00f3w<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Koszt wykonania operacji mo\u017ce by\u0107 bardzo r\u00f3\u017cny.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Przyk\u0142adowo:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>odczyt z pami\u0119ci RAM: nanosekundy<\/li>\n\n\n\n<li>odczyt z dysku SSD: mikrosekundy do milisekund<\/li>\n\n\n\n<li>zapytanie SQL do du\u017cej tabeli: milisekundy do sekund<\/li>\n\n\n\n<li>zapytanie do zewn\u0119trznego API: od setek milisekund do kilku sekund<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">R\u00f3\u017cnica jest ogromna. Je\u015bli wynik mo\u017cna pobra\u0107 z pami\u0119ci zamiast wykonywa\u0107 ponownie kosztown\u0105 operacj\u0119, oszcz\u0119dza si\u0119 czas procesora, zasoby bazy danych i cierpliwo\u015b\u0107 u\u017cytkownika.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">W praktyce cache dzia\u0142a wed\u0142ug prostego schematu:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Program sprawdza, czy wynik ju\u017c istnieje<\/li>\n\n\n\n<li>Je\u015bli tak &#8211; zwraca zapisany wynik<\/li>\n\n\n\n<li>Je\u015bli nie &#8211; wykonuje obliczenie<\/li>\n\n\n\n<li>Zapisuje rezultat<\/li>\n\n\n\n<li>Zwraca wynik<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">To jest tzw. cache hit i cache miss.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>cache hit &#8211; wynik znaleziony<\/li>\n\n\n\n<li>cache miss &#8211; wynik trzeba policzy\u0107<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Dobry system d\u0105\u017cy do wysokiego hit ratio, czyli du\u017cego procentu trafie\u0144.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"podstawowy-wzor-opisujacy-oplacalnosc-stosowania-pamieci-podrecznej\">Podstawowy wz\u00f3r opisuj\u0105cy op\u0142acalno\u015b\u0107 stosowania pami\u0119ci podr\u0119cznej<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Je\u017celi:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>czas obliczenia = 800 ms<\/li>\n\n\n\n<li>czas odczytu z cache = 5 ms<\/li>\n\n\n\n<li>liczba powt\u00f3rze\u0144 = 1000<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">to oszcz\u0119dno\u015b\u0107 jest bardzo konkretna.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Element<\/th><th>Wz\u00f3r \/ warto\u015b\u0107<\/th><\/tr><\/thead><tbody><tr><td>Czas bez cache<\/td><td>1000 \u00d7 800 ms = 800 000 ms<\/td><\/tr><tr><td>Czas z cache<\/td><td>800 ms + 999 \u00d7 5 ms = 5 795 ms<\/td><\/tr><tr><td>R\u00f3\u017cnica<\/td><td>ponad 794 sekund oszcz\u0119dno\u015bci<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To nie jest optymalizacja kosmetyczna. To zmiana zachowania ca\u0142ego systemu.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cache-wynikow-w-bazach-danych-api-i-aplikacjach-webowych-dziala-inaczej-niz-wielu-poczatkujacych-zaklada\">Cache wynik\u00f3w w bazach danych, API i aplikacjach webowych dzia\u0142a inaczej ni\u017c wielu pocz\u0105tkuj\u0105cych zak\u0142ada<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Najcz\u0119stszy b\u0142\u0105d pocz\u0105tkuj\u0105cych polega na my\u015bleniu, \u017ce cache to tylko Redis albo Memcached. To zbyt w\u0105skie spojrzenie.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cache mo\u017ce istnie\u0107:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>w pami\u0119ci procesu<\/li>\n\n\n\n<li>w plikach<\/li>\n\n\n\n<li>w bazie danych<\/li>\n\n\n\n<li>w przegl\u0105darce<\/li>\n\n\n\n<li>w reverse proxy<\/li>\n\n\n\n<li>w CDN<\/li>\n\n\n\n<li>w systemie operacyjnym<\/li>\n\n\n\n<li>w warstwie ORM<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Ka\u017cda z tych warstw rozwi\u0105zuje troch\u0119 inny problem.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"cache-zapytan-do-bazy-danych\">Cache zapyta\u0144 do bazy danych<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Za\u0142\u00f3\u017cmy tabel\u0119 produkt\u00f3w z 500 000 rekord\u00f3w. Strona g\u0142\u00f3wna sklepu co sekund\u0119 pobiera:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>10 najpopularniejszych produkt\u00f3w<\/li>\n\n\n\n<li>10 najnowszych produkt\u00f3w<\/li>\n\n\n\n<li>list\u0119 kategorii<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Je\u017celi ka\u017cde wej\u015bcie u\u017cytkownika wykonuje te same zapytania SQL, baza zaczyna pracowa\u0107 g\u0142\u00f3wnie nad powtarzalnymi odczytami.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lepiej wykona\u0107 zapytanie raz na 5 minut i przechowywa\u0107 wynik.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>SQL<\/th><th>Przyk\u0142ad<\/th><\/tr><\/thead><tbody><tr><td>Zapytanie<\/td><td><code>SELECT * FROM products ORDER BY views DESC LIMIT 10;<\/code><\/td><\/tr><tr><td>Czas wykonania bez indeks\u00f3w<\/td><td>np. 300\u2013800 ms<\/td><\/tr><tr><td>Odczyt z cache<\/td><td>cz\u0119sto poni\u017cej 10 ms<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"przyklad-w-python\">Przyk\u0142ad w Python<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>J\u0119zyk<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>Python<\/td><td><code>python\\ncache = {}\\n\\ndef pobierz_uzytkownika(user_id):\\n if user_id in cache:\\n return cache[user_id]\\n\\n wynik = \\\"Dane z bazy dla ID \\\" + str(user_id)\\n cache[user_id] = wynik\\n return wynik\\n\\nprint(pobierz_uzytkownika(5))\\nprint(pobierz_uzytkownika(5))\\n<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Pierwsze wywo\u0142anie pobiera dane \u201ez bazy\u201d, drugie korzysta ju\u017c z pami\u0119ci.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"przyklad-w-c\">Przyk\u0142ad w C<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>J\u0119zyk<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>C<\/td><td><code>c\\n#include &lt;stdio.h&gt;\\n\\nint cache[100] = {0};\\n\\nint fibonacci(int n) {\\n if (n &lt;= 1)\\n return n;\\n\\n if (cache[n] != 0)\\n return cache[n];\\n\\n cache[n] = fibonacci(n - 1) + fibonacci(n - 2);\\n return cache[n];\\n}\\n\\nint main() {\\n printf(\\\"%d\\\\n\\\", fibonacci(10));\\n return 0;\\n}\\n<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To jest klasyczny przyk\u0142ad memoizacji &#8211; bardzo bliski idei cache.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"przyklad-w-c-1\">Przyk\u0142ad w C++<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>J\u0119zyk<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>C++<\/td><td><code>cpp\\n#include &lt;iostream&gt;\\n#include &lt;map&gt;\\nusing namespace std;\\n\\nmap&lt;int, int&gt; cache;\\n\\nint square(int x) {\\n if (cache.count(x))\\n return cache[x];\\n\\n cache[x] = x * x;\\n return cache[x];\\n}\\n\\nint main() {\\n cout &lt;&lt; square(8) &lt;&lt; endl;\\n cout &lt;&lt; square(8) &lt;&lt; endl;\\n return 0;\\n}\\n<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"przyklad-w-php\">Przyk\u0142ad w PHP<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>J\u0119zyk<\/th><th>Kod<\/th><\/tr><\/thead><tbody><tr><td>PHP<\/td><td><code>php\\n&lt;?php\\n$cache = [];\\n\\nfunction getValue($id) {\\n global $cache;\\n\\n if (isset($cache[$id])) {\\n return $cache[$id];\\n }\\n\\n $result = \\\"Wynik dla ID \\\" . $id;\\n $cache[$id] = $result;\\n return $result;\\n}\\n\\necho getValue(3);\\necho getValue(3);\\n?&gt;\\n<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"cache-odpowiedzi-api\">Cache odpowiedzi API<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To bardzo cz\u0119sty przypadek.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Przyk\u0142ad:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">system pogodowy pobiera dane z zewn\u0119trznego API co 15 sekund dla ka\u017cdego u\u017cytkownika.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Je\u017celi 200 u\u017cytkownik\u00f3w otworzy stron\u0119 w tym samym czasie:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>bez cache \u2192 200 zapyta\u0144<\/li>\n\n\n\n<li>z cache 5-minutowym \u2192 1 zapytanie<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">R\u00f3\u017cnica ma znaczenie finansowe, bo wiele API rozlicza si\u0119 za liczb\u0119 request\u00f3w.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"cache-wynikow-wymaga-poprawnego-uniewazniania-danych-bo-tu-najczesciej-powstaja-realne-problemy-produkcyjne\">Cache wynik\u00f3w wymaga poprawnego uniewa\u017cniania danych bo tu najcz\u0119\u015bciej powstaj\u0105 realne problemy produkcyjne<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Najtrudniejsza cz\u0119\u015b\u0107 nie polega na zapisaniu danych, tylko na decyzji, kiedy je usun\u0105\u0107.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Stare dane bywaj\u0105 gorsze ni\u017c brak danych.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Je\u017celi sklep pokazuje nieaktualny stan magazynowy, u\u017cytkownik mo\u017ce zap\u0142aci\u0107 za produkt, kt\u00f3rego ju\u017c nie ma. Wtedy problem nie jest techniczny, tylko biznesowy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"najczestsze-strategie-wygaszania-cache\">Najcz\u0119stsze strategie wygaszania cache<\/h3>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"ttl-time-to-live\">TTL &#8211; Time To Live<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dane maj\u0105 okre\u015blony czas \u017cycia.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Przyk\u0142ad:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>kurs walut: 10 minut<\/li>\n\n\n\n<li>ranking produkt\u00f3w: 1 godzina<\/li>\n\n\n\n<li>dane u\u017cytkownika premium: 5 minut<\/li>\n\n\n\n<li>konfiguracja systemu: 24 godziny<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Po up\u0142ywie czasu wpis jest usuwany lub od\u015bwie\u017cany.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"invalidation-po-zmianie-danych\">Invalidation po zmianie danych<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Je\u017celi produkt zosta\u0142 edytowany:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>stary wpis cache nale\u017cy usun\u0105\u0107 natychmiast<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">To podej\u015bcie jest dok\u0142adniejsze, ale trudniejsze implementacyjnie.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"lru-least-recently-used\">LRU &#8211; Least Recently Used<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Je\u017celi pami\u0119\u0107 si\u0119 ko\u0144czy:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>usuwane s\u0105 dane najdawniej u\u017cywane<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">To standard w wielu systemach cache.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"praktyczny-wzor-na-wspolczynnik-trafien\">Praktyczny wz\u00f3r na wsp\u00f3\u0142czynnik trafie\u0144<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Element<\/th><th>Wz\u00f3r<\/th><\/tr><\/thead><tbody><tr><td>Hit Ratio<\/td><td>liczba trafie\u0144 \/ wszystkie zapytania \u00d7 100%<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Przyk\u0142ad:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>920 trafie\u0144<\/li>\n\n\n\n<li>1000 zapyta\u0144<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Wynik<\/th><th>Obliczenie<\/th><\/tr><\/thead><tbody><tr><td>Hit Ratio<\/td><td>920 \/ 1000 \u00d7 100% = 92%<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Dla system\u00f3w produkcyjnych cz\u0119sto oczekuje si\u0119 warto\u015bci powy\u017cej 80\u201390%, ale zale\u017cy to od typu danych.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"typowe-pulapki\">Typowe pu\u0142apki<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"cache-wszystkiego\">Cache wszystkiego<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Nie ka\u017cda operacja wymaga cache.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Je\u017celi obliczenie trwa 2 ms, a obs\u0142uga cache 4 ms, zysk nie istnieje.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"brak-limitu-pamieci\">Brak limitu pami\u0119ci<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">\u0179le zaprojektowany cache potrafi zaj\u0105\u0107 ca\u0142\u0105 pami\u0119\u0107 RAM i przewr\u00f3ci\u0107 aplikacj\u0119 szybciej ni\u017c brak cache.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"brak-monitoringu\">Brak monitoringu<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Je\u017celi nie wiadomo:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ile jest trafie\u0144<\/li>\n\n\n\n<li>ile jest b\u0142\u0119d\u00f3w<\/li>\n\n\n\n<li>ile wpis\u00f3w wygasa<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">to nie wiadomo r\u00f3wnie\u017c, czy mechanizm dzia\u0142a poprawnie.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"zbyt-dlugi-ttl\">Zbyt d\u0142ugi TTL<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">U\u017cytkownik widzi stare dane i traci zaufanie do systemu.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To cz\u0119sty problem w panelach administracyjnych.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"cache-danych-wrazliwych-bez-kontroli\">Cache danych wra\u017cliwych bez kontroli<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Nie mo\u017cna bezrefleksyjnie przechowywa\u0107:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>token\u00f3w<\/li>\n\n\n\n<li>danych p\u0142atniczych<\/li>\n\n\n\n<li>danych medycznych<\/li>\n\n\n\n<li>danych prywatnych u\u017cytkownika<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Tutaj bezpiecze\u0144stwo jest wa\u017cniejsze ni\u017c szybko\u015b\u0107.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"faq\">FAQ<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-cache-zawsze-przyspiesza-aplikacje\">Czy cache zawsze przyspiesza aplikacj\u0119<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nie. Je\u015bli operacja jest tania obliczeniowo albo dane zmieniaj\u0105 si\u0119 bardzo cz\u0119sto, koszt zarz\u0105dzania pami\u0119ci\u0105 podr\u0119czn\u0105 mo\u017ce by\u0107 wi\u0119kszy ni\u017c zysk.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-redis-jest-obowiazkowy\">Czy Redis jest obowi\u0105zkowy<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nie. Redis jest wygodnym narz\u0119dziem, ale prosty cache mo\u017ce dzia\u0142a\u0107 w pami\u0119ci procesu, w plikach albo nawet w zwyk\u0142ej tabeli bazy danych.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"czy-cache-moze-powodowac-bledy-biznesowe\">Czy cache mo\u017ce powodowa\u0107 b\u0142\u0119dy biznesowe<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Tak, i to bardzo kosztowne. Najcz\u0119\u015bciej s\u0105 to nieaktualne ceny, b\u0142\u0119dne stany magazynowe albo stare uprawnienia u\u017cytkownika.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"memoizacja-i-cache-to-to-samo\">Memoizacja i cache to to samo<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nie ca\u0142kiem. Memoizacja zwykle dotyczy funkcji i oblicze\u0144 w kodzie, a cache jest poj\u0119ciem szerszym i obejmuje wiele warstw systemu.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"kiedy-najlepiej-wdrazac-cache\">Kiedy najlepiej wdra\u017ca\u0107 cache<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Najpierw trzeba zmierzy\u0107 problem. Wdra\u017canie pami\u0119ci podr\u0119cznej bez analizy bywa strat\u0105 czasu. Najpierw profilowanie, potem decyzja.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dobrze zaprojektowany system nie u\u017cywa pami\u0119ci podr\u0119cznej wsz\u0119dzie, tylko tam, gdzie koszt ponownego wykonania operacji naprawd\u0119 boli. W praktyce najwi\u0119cej problem\u00f3w nie wynika z samego przechowywania wynik\u00f3w, ale z niepoprawnego od\u015bwie\u017cania danych. To w\u0142a\u015bnie tam zwykle ko\u0144czy si\u0119 teoria i zaczyna prawdziwa praca produkcyjna.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>\u0179r\u00f3d\u0142o Foto: Freepik<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Systemy informatyczne bardzo rzadko przegrywaj\u0105 przez brak funkcjonalno\u015bci. Znacznie cz\u0119\u015bciej problemem jest czas odpowiedzi, nadmierne obci\u0105\u017cenie bazy danych, zbyt du\u017ca liczba zapyta\u0144 do API albo niepotrzebne przeliczanie tych samych danych setki razy na minut\u0119. U\u017cytkownik nie widzi wtedy algorytm\u00f3w ani architektury &#8211; widzi tylko woln\u0105 stron\u0119, zawieszaj\u0105cy si\u0119 panel albo raport generuj\u0105cy si\u0119 przez kilka minut. Jednym z najprostszych i jednocze\u015bnie najskuteczniejszych sposob\u00f3w ograniczenia tego problemu jest Cache wynik\u00f3w. Cache wynik\u00f3w jako mechanizm ograniczania kosztu wielokrotnego wykonywania tych samych operacji Najprostsza definicja jest praktyczna: je\u017celi program raz obliczy\u0142 wynik i istnieje du\u017ce prawdopodobie\u0144stwo, \u017ce za chwil\u0119 b\u0119dzie potrzebowa\u0142 dok\u0142adnie tego samego rezultatu, warto ten rezultat zachowa\u0107 i u\u017cy\u0107 ponownie zamiast liczy\u0107 od pocz\u0105tku. To podej\u015bcie dotyczy wielu warstw systemu: Koszt wykonania operacji mo\u017ce by\u0107 bardzo r\u00f3\u017cny. Przyk\u0142adowo: R\u00f3\u017cnica jest ogromna. Je\u015bli wynik mo\u017cna pobra\u0107 z pami\u0119ci zamiast wykonywa\u0107 ponownie kosztown\u0105 operacj\u0119, oszcz\u0119dza si\u0119 czas procesora, zasoby bazy danych i cierpliwo\u015b\u0107 u\u017cytkownika. W praktyce cache dzia\u0142a wed\u0142ug prostego schematu: To jest tzw. cache hit i cache miss. Dobry system d\u0105\u017cy do wysokiego hit ratio, czyli du\u017cego procentu trafie\u0144. Podstawowy wz\u00f3r opisuj\u0105cy op\u0142acalno\u015b\u0107 stosowania pami\u0119ci podr\u0119cznej Je\u017celi: to oszcz\u0119dno\u015b\u0107 jest bardzo konkretna. Element Wz\u00f3r \/ warto\u015b\u0107 Czas bez cache 1000 \u00d7 800 ms = 800 000 ms Czas z cache 800 ms + 999 \u00d7 5 ms = 5 795 ms R\u00f3\u017cnica ponad 794 sekund oszcz\u0119dno\u015bci To nie jest optymalizacja kosmetyczna. To zmiana zachowania ca\u0142ego systemu. Cache wynik\u00f3w w bazach danych, API i aplikacjach webowych dzia\u0142a inaczej ni\u017c wielu pocz\u0105tkuj\u0105cych zak\u0142ada Najcz\u0119stszy b\u0142\u0105d pocz\u0105tkuj\u0105cych polega na my\u015bleniu, \u017ce cache to tylko Redis albo Memcached. To zbyt w\u0105skie spojrzenie. Cache mo\u017ce istnie\u0107: Ka\u017cda z tych warstw rozwi\u0105zuje troch\u0119 inny problem. Cache zapyta\u0144 do bazy danych Za\u0142\u00f3\u017cmy tabel\u0119 produkt\u00f3w z 500 000 rekord\u00f3w. Strona g\u0142\u00f3wna sklepu co sekund\u0119 pobiera: Je\u017celi ka\u017cde wej\u015bcie u\u017cytkownika wykonuje te same zapytania SQL, baza zaczyna pracowa\u0107 g\u0142\u00f3wnie nad powtarzalnymi odczytami. Lepiej wykona\u0107 zapytanie raz na 5 minut i przechowywa\u0107 wynik. SQL Przyk\u0142ad Zapytanie SELECT * FROM products ORDER BY views DESC LIMIT 10; Czas wykonania bez indeks\u00f3w np. 300\u2013800 ms Odczyt z cache cz\u0119sto poni\u017cej 10 ms Przyk\u0142ad w Python J\u0119zyk Kod Python python\\ncache = {}\\n\\ndef pobierz_uzytkownika(user_id):\\n if user_id in cache:\\n return cache[user_id]\\n\\n wynik = \\&#8221;Dane z bazy dla ID \\&#8221; + str(user_id)\\n cache[user_id] = wynik\\n return wynik\\n\\nprint(pobierz_uzytkownika(5))\\nprint(pobierz_uzytkownika(5))\\n Pierwsze wywo\u0142anie pobiera dane \u201ez bazy\u201d, drugie korzysta ju\u017c z pami\u0119ci. Przyk\u0142ad w C J\u0119zyk Kod C c\\n#include &lt;stdio.h&gt;\\n\\nint cache[100] = {0};\\n\\nint fibonacci(int n) {\\n if (n &lt;= 1)\\n return n;\\n\\n if (cache[n] != 0)\\n return cache[n];\\n\\n cache[n] = fibonacci(n &#8211; 1) + fibonacci(n &#8211; 2);\\n return cache[n];\\n}\\n\\nint main() {\\n printf(\\&#8221;%d\\\\n\\&#8221;, fibonacci(10));\\n return 0;\\n}\\n To jest klasyczny przyk\u0142ad memoizacji &#8211; bardzo bliski idei cache. Przyk\u0142ad w C++ J\u0119zyk Kod C++ cpp\\n#include &lt;iostream&gt;\\n#include &lt;map&gt;\\nusing namespace std;\\n\\nmap&lt;int, int&gt; cache;\\n\\nint square(int x) {\\n if (cache.count(x))\\n return cache[x];\\n\\n cache[x] = x * x;\\n return cache[x];\\n}\\n\\nint main() {\\n cout &lt;&lt; square(8) &lt;&lt; endl;\\n cout &lt;&lt; square(8) &lt;&lt; endl;\\n return 0;\\n}\\n Przyk\u0142ad w PHP J\u0119zyk Kod PHP php\\n&lt;?php\\n$cache = [];\\n\\nfunction getValue($id) {\\n global $cache;\\n\\n if (isset($cache[$id])) {\\n return $cache[$id];\\n }\\n\\n $result = \\&#8221;Wynik dla ID \\&#8221; . $id;\\n $cache[$id] = $result;\\n return $result;\\n}\\n\\necho getValue(3);\\necho getValue(3);\\n?&gt;\\n Cache odpowiedzi API To bardzo cz\u0119sty przypadek. Przyk\u0142ad: system pogodowy pobiera dane z zewn\u0119trznego API co 15 sekund dla ka\u017cdego u\u017cytkownika. Je\u017celi 200 u\u017cytkownik\u00f3w otworzy stron\u0119 w tym samym czasie: R\u00f3\u017cnica ma znaczenie finansowe, bo wiele API rozlicza si\u0119 za liczb\u0119 request\u00f3w. Cache wynik\u00f3w wymaga poprawnego uniewa\u017cniania danych bo tu najcz\u0119\u015bciej powstaj\u0105 realne problemy produkcyjne Najtrudniejsza cz\u0119\u015b\u0107 nie polega na zapisaniu danych, tylko na decyzji, kiedy je usun\u0105\u0107. Stare dane bywaj\u0105 gorsze ni\u017c brak danych. Je\u017celi sklep pokazuje nieaktualny stan magazynowy, u\u017cytkownik mo\u017ce zap\u0142aci\u0107 za produkt, kt\u00f3rego ju\u017c nie ma. Wtedy problem nie jest techniczny, tylko biznesowy. Najcz\u0119stsze strategie wygaszania cache TTL &#8211; Time To Live Dane maj\u0105 okre\u015blony czas \u017cycia. Przyk\u0142ad: Po up\u0142ywie czasu wpis jest usuwany lub od\u015bwie\u017cany. Invalidation po zmianie danych Je\u017celi produkt zosta\u0142 edytowany: To podej\u015bcie jest dok\u0142adniejsze, ale trudniejsze implementacyjnie. LRU &#8211; Least Recently Used Je\u017celi pami\u0119\u0107 si\u0119 ko\u0144czy: To standard w wielu systemach cache. Praktyczny wz\u00f3r na wsp\u00f3\u0142czynnik trafie\u0144 Element Wz\u00f3r Hit Ratio liczba trafie\u0144 \/ wszystkie zapytania \u00d7 100% Przyk\u0142ad: Wynik Obliczenie Hit Ratio 920 \/ 1000 \u00d7 100% = 92% Dla system\u00f3w produkcyjnych cz\u0119sto oczekuje si\u0119 warto\u015bci powy\u017cej 80\u201390%, ale zale\u017cy to od typu danych. Typowe pu\u0142apki Cache wszystkiego Nie ka\u017cda operacja wymaga cache. Je\u017celi obliczenie trwa 2 ms, a obs\u0142uga cache 4 ms, zysk nie istnieje. Brak limitu pami\u0119ci \u0179le zaprojektowany cache potrafi zaj\u0105\u0107 ca\u0142\u0105 pami\u0119\u0107 RAM i przewr\u00f3ci\u0107 aplikacj\u0119 szybciej ni\u017c brak cache. Brak monitoringu Je\u017celi nie wiadomo: to nie wiadomo r\u00f3wnie\u017c, czy mechanizm dzia\u0142a poprawnie. Zbyt d\u0142ugi TTL U\u017cytkownik widzi stare dane i traci zaufanie do systemu. To cz\u0119sty problem w panelach administracyjnych. Cache danych wra\u017cliwych bez kontroli Nie mo\u017cna bezrefleksyjnie przechowywa\u0107: Tutaj bezpiecze\u0144stwo jest wa\u017cniejsze ni\u017c szybko\u015b\u0107. FAQ Czy cache zawsze przyspiesza aplikacj\u0119 Nie. Je\u015bli operacja jest tania obliczeniowo albo dane zmieniaj\u0105 si\u0119 bardzo cz\u0119sto, koszt zarz\u0105dzania pami\u0119ci\u0105 podr\u0119czn\u0105 mo\u017ce by\u0107 wi\u0119kszy ni\u017c zysk. Czy Redis jest obowi\u0105zkowy Nie. Redis jest wygodnym narz\u0119dziem, ale prosty cache mo\u017ce dzia\u0142a\u0107 w pami\u0119ci procesu, w plikach albo nawet w zwyk\u0142ej tabeli bazy danych. Czy cache mo\u017ce powodowa\u0107 b\u0142\u0119dy biznesowe Tak, i to bardzo kosztowne. Najcz\u0119\u015bciej s\u0105 to nieaktualne ceny, b\u0142\u0119dne stany magazynowe albo stare uprawnienia u\u017cytkownika. Memoizacja i cache to to samo Nie ca\u0142kiem. Memoizacja zwykle dotyczy funkcji i oblicze\u0144 w kodzie, a cache jest poj\u0119ciem szerszym i obejmuje wiele warstw systemu. Kiedy najlepiej wdra\u017ca\u0107 cache Najpierw trzeba zmierzy\u0107 problem. Wdra\u017canie pami\u0119ci podr\u0119cznej bez analizy bywa strat\u0105 czasu. Najpierw profilowanie, potem decyzja. Dobrze zaprojektowany system nie u\u017cywa pami\u0119ci podr\u0119cznej wsz\u0119dzie, tylko tam, gdzie koszt ponownego wykonania operacji naprawd\u0119 boli. W praktyce najwi\u0119cej problem\u00f3w nie wynika z samego przechowywania wynik\u00f3w, ale z niepoprawnego od\u015bwie\u017cania danych. To w\u0142a\u015bnie tam zwykle ko\u0144czy si\u0119 teoria i zaczyna prawdziwa praca produkcyjna. \u0179r\u00f3d\u0142o Foto: Freepik<\/p>\n","protected":false},"author":1,"featured_media":1359,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,1],"tags":[],"class_list":["post-1358","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kodowanie","category-poradnik"],"_links":{"self":[{"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts\/1358","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/comments?post=1358"}],"version-history":[{"count":1,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts\/1358\/revisions"}],"predecessor-version":[{"id":1360,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/posts\/1358\/revisions\/1360"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/media\/1359"}],"wp:attachment":[{"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/media?parent=1358"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/categories?post=1358"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trzykody.pl\/index.php\/wp-json\/wp\/v2\/tags?post=1358"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}