Strategie buforowania
1) Dlaczego cache i gdzie to zrobić
Cache to szybka warstwa pamięci, która zmniejsza opóźnienie i obciążenie drogich zasobów (CPU/DB/zewnętrzny API). Ważne cele:- Prędkość (p95/p99 niższa), koszt (mniej egress/CPU), stabilność (mniej zależności pod szczytem).
- Szczyt wygładzania i izolacji od „hałaśliwych sąsiadów”.
1. Klient (przeglądarka/mobilna) - pamięć podręczna HTTP, IndexedDB, pamięć lokalna.
2. Krawędź/CDN - węzły POP są bliżej użytkownika, cache statyczne i część API.
3. L7-gateway/Reverse-proxy - Nginx/Envoy/Lakier (mikrokas, SWR).
4. Pamięć podręczna usługi - Redis/Memcached w klastrze.
5. Proces - pamięć (kofeina/gawa/mapa LRU).
6. Pamięć podręczna w bazie danych - reprezentacje materiałów, indeksy wtórne.
Zasada: pamięć podręczna jak najbliżej konsumenta, ale zachowaj prawdę raz.
2) Wzory pamięci podręcznej
2. 1 Cache-off („leniwe obciążenie”)
Aplikacja najpierw odczytuje z pamięci podręcznej; w przypadku miss - ze źródła, a następnie pisze do pamięci podręcznej.
Plusy: prostota, kontrola. Minusy: zimno zaczyna, niedopasowanie okien.
2. 2 Czytanie
Czytanie jest zawsze przez pamięć podręczną, która sama trafia do źródła, gdy brakuje (biblioteka/warstwa proxy).
Wygodnie jest scentralizować zasady TTL/serializacji.
2. 3 Odpis/odpis (odpis)
Zapis: zapisz do pamięci podręcznej i źródła synchronicznie → konsystencja wyższa, opóźnienie wyższe.
Odpis: napisz do pamięci podręcznej, asynchroniczny flash napisz do źródła → szybko, ale ryzyko utraty i konfliktu.
2. 4 Odświeżanie z przodu (proaktywne)
Przewiduje „TTL wygaśnie wkrótce” i aktualizuje klucz w tle, zapobiegając stampede.
2. 5 Buforowanie ujemne
Buforowanie „brak danych/404/puste” do krótkiego TTL zmniejsza obciążenie źródła.
2. 6 Mikro-buforowanie
Bardzo krótkie TTL (0. 5-5 s) na L7 dla „prawie dynamiki” (listy, główne) - gwałtownie zmniejsza ogony.
3) pamięć podręczna HTTP: nagłówki i sterowanie
3. 1 Podstawowe pozycje
„Cache-Control”: „max-age”, „s-maxage” (дла podzielił się крей), „public/private”, „no-store”, „stale-while-revalidate”, „steady-if-error”.
Walidatory: 'ETag' (hash treści), 'Last-Modified'.
Zapytania z warunkami: „If-None-Match”, „If-Modified-Since” → 304 Not Modified.
3. 2 Różne i klucze
'Vary: Accept-Encoding, Authorization, Cookie, Accept-Language' - generuje różne opcje pamięci podręcznej. Zminimalizuj 'Vary', aby nie „wysadzić” kardynalności.
3. 3 Przykład odpowiedzi HTTP
Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=60
ETag: "a1b2c3"
Vary: Accept-Encoding
4) Kluczowy projekt i TTL
4. 1 klucze
Struktura: 'najemca: user: {id}: profile: v3' (zawiera wersję schematu).
Unikaj PII w kluczu.
Dla kolekcji - klucz + parametry zapytania (znormalizowane i sortowane).
4. 2 TTL i spójność
Krótki TTL zmniejsza niedopasowanie, ale zwiększa braki.
Dla danych krytycznych - walidatory („ETag”) i SWR (stale-while-revalidate).
Dla rzadko zmieniających się - długie TTL + „bomby” niepełnosprawności.
4. 3 Wersioning/basting
W przypadku niezgodnych zmian zmień wersję prefiksu/klucza ('v2 → v3').
Dla zasobów statycznych - hash zawartości w nazwie pliku.
5) Niepełnosprawność: strategie i praktyki
5. 1 Skreślenie bezpośrednie
'DEL key '/' PURGE' na serwerze proxy. Niebezpieczeństwo: Wyścigi między usunięciem a wieloma czytnikami.
5. 2 klucze zastępcze
Skojarzyć dokument z zestawem znaczników (kategoria/autor). Niepełnosprawność - według tagu.
Корович/Edge - 'Surrogate-Key: article: 42 tag: autor: 7' + 'BAN tag: author: 7'.
5. 3 Niepełnosprawność spowodowana zdarzeniami
Pub/Sub (Kafka/NATS): kiedy zmieni się źródło, publikujemy wydarzenie „unieważnić”.
Klienci pamięci podręcznej słuchają i usuwają/aktualizują klucze.
5. 4 Dwufazowe
Po pierwsze, oznaczamy klucz przestarzały (miękki TTL), obsługujemy stale, aktualizujemy go w tle i atomowo go zastępujemy.
6) Zajmowanie się stampede/dogpile i gorące klucze
6. 1 Żądanie koalescencji (single flight)
Jeden producent aktualizuje klucz, reszta czeka na wynik (mutex/label „updates”).
6. 2 Jitter, TTL
Dodać losowość (± 10-20%) do TTL, aby uniknąć synchronicznego obrzęku.
6. 3 Soft-TTL + hard-TTL
Przed miękkim TTL służymy z pamięci podręcznej, równolegle z zapalnikiem odświeżającym; przez hard-TTL - uważamy za miss.
6. 4 gorące klucze
Lokalne bufory nad wspólnymi (dwupoziomowe).
Replikacja hot-key na wiele odłamków i wybór losowy (tylko do odczytu).
Limit stawki dla aktualizacji konkretnego klucza.
6. 5 Przykład Redis + Lua (szkic typu single-flight)
lua
-- SETNX lock with TTL to avoid deadlocks local ok = redis. call("SET", KEYS[1], "1", "NX", "EX", ARGV[1])
if ok then return "LOCKED"
else return "WAIT"
end
7) Zasady preempcji i odbiór pamięci podręcznej
7. 1 Eksmisja
LRU: proste i dobre dla miejscowości.
LFU: Lepsze dla „długotrwałych” gorących kluczy.
ARC/TacterLFU: bilans rekordów/częstotliwości.
7. 2 Wstęp
Nie wpuszczaj do gigantycznych obiektów rzadkich (filtry TmLFU/Bloom).
Kompresja dużych wartości (LZ4/Zstd) na granicy wielkości/opóźnienia.
8) Charding i topologie
8. 1 Konsekwentne hashing
Stabilnie rozprowadza klucze do węzłów, zmniejsza ruch podczas wzrostu/kompresji klastra.
8. 2 topologie Redis/Memcached
Klaster Redis (sloty/odłamki), Sentinel (feilover), replikacja tylko do odczytu.
Memcached jest shading po stronie klienta (ketama hashing), bez replikacji na poziomie serwera.
8. 3 lokalne + rozproszone
Kaskada: in-proc (micro-TTL/LRU) → Redis (TTL dłużej) → źródło.
Uważaj na okrężnice TTL i walidatory pamięci podręcznej.
9) Pamięć podręczna krawędzi, CDN i L7
9. 1 Mikro-cache на Nginx
nginx proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=api:100m inactive=10m;
map $request_method $skip_cache { default 0; POST 1; PUT 1; DELETE 1; }
server {
location /api/list {
if ($skip_cache) { add_header Cache-Control "no-store"; }
proxy_cache api;
proxy_cache_valid 200 2s; # micro-cache proxy_cache_use_stale error timeout updating;
proxy_cache_background_update on; # SWR add_header X-Cache $upstream_cache_status;
proxy_pass http://upstream;
}
}
9. 2 Wysłannik (SWR i warunki)
yaml http_filters:
- name: envoy. filters. http. cache typed_config:
"@type": type. googleapis. com/envoy. extensions. filters. http. cache. v3. CacheConfig typed_config:
"@type": type. googleapis. com/envoy. extensions. http. cache. file_system_http_cache. v3. FileSystemHttpCacheConfig cache_path: "/var/cache/envoy"
9. 3 Lakier (klucze zastępcze)
Użyj „klucza zastępczego” i „zakazu” na tagach dla niepełnosprawności partii.
10) Pamięć podręczna i spójność danych
10. 1 Czytaj swoje pisma
W przypadku profili użytkownika/koszyka do recyklingu należy podać krótkie TTL, zapis lub oznaczenie klienta (obwodnica przez N sekund po napisaniu).
10. 2 Eventual vs Strong
Dla rekomendacyjnych/analitycznych - eventual + long TTL.
Dla statusów pieniędzy/zamówień - krótki TTL, walidacja, czasami bez pamięci podręcznej na ścieżkach krytycznych.
10. 3 Niezmienne
Nie buforować pól, które wpływają na bezpieczeństwo/ACL bez ścisłych TTL i ponownej walidacji.
11) Obserwowalność, SLO i zarządzanie
11. 1 Metryka
hit_ratio (овеий а na trasie), byte_hit_ratio, miss_rate.
stampede_prevented_total, refresh_ahead_total, ban/purge_total.
Opóźnienie: p50/p95/p99 z pamięci podręcznej vs ze źródła.
hot_keys_topN i ich QPS/bajty.
11. 2 Kłody i ślady
Log 'X-Cache: HIT/MISS/STALE/UPDATING'.
W śladach zaznacz źródło odpowiedzi ('cache = true', 'tier = edge' service 'local').
11. 3 podejście SLO
Przykład: "dla API/katalogu p99 ≤ 250 ms, cache trafienie ≥ 85%, stampede ≤ 0. 1% żądań"
11. 4 Książki startowe
„Misses grow” → sprawdź TTL, rozgrzewkę/niepełnosprawność, gorące klawisze, rozmiar pamięci podręcznej i zasady akceptacji.
12) Bezpieczeństwo i wielopoziomowość
Wbudowany lokator-id w klucze (i w 'Vary' dla HTTP).
Nie buforuj prywatnych odpowiedzi jako „publicznych”.
Szyfruj pamięć podręczną z danymi wrażliwymi lub przechowuj tylko dane inne niż PII/ID.
13) Typowe przepisy kulinarne
13. 1 Katalog/Taśma (prawie dynamiczny)
Krawędź-mikrokas 1-3 s + SWR, wewnątrz - Redis dla 15-60 s, niepełnosprawność poprzez aktualizację zdarzeń.
13. 2 Profil użytkownika
Cache-off z TTL 30-120 s, ominąć 5-10 s po aktualizacji profilu (cookie/nagłówek), lub zapisać.
13. 3 Kursy walutowe/książki referencyjne
Długi TTL (minuty-godziny) + niepełnosprawność docelowa po opublikowaniu nowych danych; „ETag” dla warunkowych LZ.
13. 4 Wyniki wyszukiwania
Krawędź-mikrokas 1-2 s, wewnątrz - odświeżanie i koalescowanie, normalizacja parametrów zapytania w kluczu.
14) Anty-wzory
Gotówka bez niepełnosprawności: nadzieja tylko dla TTL → długie okna nieistotne.
Gigant 'Vary': „eksplozja” opcji → niski wskaźnik trafień.
Pojedynczy pamięć podręczna do prod/eksperymenty → zanieczyszczenie.
Brak ochrony przed stampede → kolce źródłowe po wygaśnięciu TTL.
Gotówka/prawa/pamięć podręczna ACL bez ścisłych gwarancji.
Kompresja „wszystko z rzędu” - dodatkowe procesory, pogorszenie p99 na małych obiektach.
15) Lista kontrolna wdrażania
- Określić poziomy pamięci podręcznej i ich cele (krawędź/usługa/lokalna).
- Klucze projektowe (wersioning, najemca, normalizacja parametrów).
- Wybierz wzór (cache-aside/read-through/refresh-ahead).
- Skonfiguruj TTL/soft-TTL/jitter, włącz SWR.
- Wdrożenie koalescencji/oświetlenia pojedynczego, ochrona stampede.
- Organizowanie niepełnosprawności (wydarzenia, tagi, czystość/zakaz).
- Wprowadź wskaźniki współczynnika trafienia/opóźnienia i deski rozdzielcze 'X-Cache'.
- Wykonaj badania obciążenia kluczem gorącym.
- Napisz SLO i książki startowe.
- Sprawdź izolację bezpieczeństwa/lokatora i 'Vary'.
16) FAQ
P: Co wybrać - cache-off lub read-through?
Odp.: Dla prostych usług - cache-off. Potrzebujemy centralizacji i jednej polityki - odczytu.
P: Jak zrozumieć optymalny TTL?
Odp.: Zacznij od dopuszczalnej przestarzałości, częstotliwości aktualizacji i docelowego trafienia; dodać jitter i obserwować p95/p99/koszt.
P: Kiedy jest właściwe odpisanie?
Odp.: Dla strumieni o dużym obciążeniu, gdzie możliwa jest ewentualna konsystencja i istnieje niezawodna kolejka/dziennik dla „dodawania”.
P: Czy autoryzowane odpowiedzi mogą być buforowane?
Odp.: Tak, ale należy zaznaczyć „prywatny” i/lub włączyć najemcę/użytkownika do przełącznika/„ Zmienny ”. Na prawdziwie prywatne - cache klienta.
P: Jak rozgrzać pamięć podręczną?
Odp.: Listy popularnych kluczy, tło wormer, powtórka z dzienników, ocieplenie przed wydaniem/szczyt (czarny piątek, itp.).
17) Kwoty całkowite
Skuteczne buforowanie to kluczowa konstrukcja + rozsądny TTL + dobrze dobrany wzór, wzmocniony niepełnosprawnością zdarzeń, SWR/refresh-ahead i ochroną stampede. Poziom pamięci podręcznej (klient/krawędź/usługa), dodać obserwowalność i SLO - i uzyskać stabilne ogony opóźnienia, przewidywalny koszt i maksymalną odporność.