![translation](https://cdn.durumis.com/common/trans.png)
To jest post przetłumaczony przez AI.
Wybierz język
Tekst podsumowany przez sztuczną inteligencję durumis
- Pamięć podręczna to technika przechowywania danych, które są często odczytywane i rzadko zapisywane, w celu zwiększenia wydajności usług. APM, takie jak DataDog, umożliwiają analizę historii wywołań zapytań RDB w celu wyboru danych do buforowania.
- Buforowanie lokalne to metoda przechowywania danych buforowanych w pamięci serwera aplikacji. Jest to szybkie, ale może prowadzić do problemów z synchronizacją pamięci podręcznej między instancjami. Buforowanie globalne wykorzystuje oddzielny serwer, taki jak Redis, do przechowywania danych buforowanych, umożliwiając współdzielenie między instancjami, ale może być wolniejsze ze względu na ruch sieciowy.
- W celu aktualizacji pamięci podręcznej stosuje się TTL (Time To Live). W przypadku, gdy odczyt/zapis występuje na jednym serwerze, zaleca się ustawienie TTL na poziomie co najmniej godzin. W przypadku występowania na wielu serwerach, zaleca się ustawienie TTL na poziomie sekund/minut.
Cześć! Jestem Jayon.
Dzisiaj zamierzam wyjaśnić kryteria konfigurowania pamięci podręcznej. To wpis oparty na moim osobistym doświadczeniu z pracy, dlatego traktujcie go jedynie jako punkt odniesienia ㅎㅎ
Czym jest pamięć podręczna?
Pamięć podręczna to mechanizm przechowujący wyniki przyszłych żądań w celu zapewnienia szybkiego dostępu. Oznacza to, że zapisujemy wyniki z wyprzedzeniem, a gdy pojawia się żądanie, zamiast odwoływać się do bazy danych lub interfejsu API, pobieramy je z pamięci podręcznej. W tle tego mechanizmu leży prawo Pareto.
Prawo Pareto mówi, że 80% wyników wynika z 20% przyczyn. Spójrzcie na to zdjęcie!
Innymi słowy, nie musimy przechowywać w pamięci podręcznej wszystkich wyników. Wystarczy przechować te 20%, które są najczęściej używane, aby zwiększyć ogólną wydajność.
Jakie dane należy przechowywać w pamięci podręcznej?
Zgodnie z prawem Pareto, nie powinniśmy przechowywać w pamięci podręcznej dowolnych danych, tylko te niezbędne. Jak więc określić, które dane warto przechować?
Dane, które są często odczytywane, ale rzadko zapisywane
W teorii często mówi się, że „należy przechować w pamięci podręcznej dane, które są często odczytywane, ale rzadko zapisywane”. Jednak kryteria „częstego odczytu” i „rzadkiego zapisu” były dość niejasne.
Dlatego ja analizuję dane do przechowywania w pamięci podręcznej w następujących krokach:
- Za pomocą narzędzi APM, takich jak DataDog, sprawdzam 5 najczęściej wywoływanych zapytań do bazy danych RDB.
- Wśród nich szukam zapytań o odczyt i sprawdzam, z której tabeli pochodzą.
- Sprawdzam, jak często wywoływane są zapytania o aktualizację danej tabeli.
Ten proces pozwala mi ocenić, czy dane są często odczytywane, a aktualizacje są rzadkie. W mojej pracy napotkałem tabelę, w której zapytania o odczyt były wywoływane 1,74 miliona razy dziennie, podczas gdy aktualizacje były wykonywane maksymalnie 500 razy. To ewidentnie wskazuje, że takie dane idealnie nadają się do pamięci podręcznej ㅎㅎ
Dane wrażliwe na aktualizacje
W przypadku danych wrażliwych na aktualizacje, czas synchronizacji danych między bazą danych RDB a pamięcią podręczną musi być krótki. Na przykład informacje związane z płatnościami są bardzo wrażliwe na aktualizacje, więc nawet jeśli spełniają powyższe warunki, należy się zastanowić nad ich zastosowaniem.
W swojej pracy musiałem zastosować pamięć podręczną dla tabeli związanej z płatnościami, która spełniała oba te wymagania. Nie zastosowałem jednak pamięci podręcznej do wszystkich funkcji korzystających z tej tabeli. Zamiast tego zdecydowałem się na częściowe użycie pamięci podręcznej tylko w funkcjach, które nie są bezpośrednio związane z procesem płatności i są relatywnie bezpieczne.
Pamięć podręczna lokalna vs globalna
Teraz, gdy już wiemy, jakie dane i w jakim zakresie chcemy przechowywać w pamięci podręcznej, musimy zdecydować, gdzie je umieścić. Zazwyczaj można przechowywać je w pamięci lokalnej lub na oddzielnym serwerze, np. Redis.
Pamięć podręczna lokalna
Pamięć podręczna lokalna to sposób przechowywania danych w pamięci serwera aplikacji. Popularne rozwiązania to Guava cache lub Caffeine cache.
Zalety
- Dane są przechowywane w pamięci tego samego serwera, z którego wykonywana jest logika aplikacji, co zapewnia szybką dostępność.
- Prosta implementacja.
Wady
- W przypadku wielu instancji pojawiają się problemy:
- Zmiany w pamięci podręcznej w jednej instancji nie są propagowane do innych. Istnieją jednak biblioteki do pamięci podręcznej lokalnej, które obsługują propagację zmian.
- Każda instancja przechowuje własną pamięć podręczną. W przypadku uruchomienia nowej instancji, należy ponownie załadować do niej dane. To może prowadzić do wielu błędów pamięci podręcznej (cache miss) i przeciążenia instancji, co z kolei może prowadzić do ich awarii.
Pamięć podręczna globalna
Pamięć podręczna globalna polega na zastosowaniu oddzielnego serwera do przechowywania danych, np. Redis.
Zalety
- Pamięć podręczna jest współdzielona między instancjami, co oznacza, że zmiana w jednej instancji jest widoczna we wszystkich.
- W przypadku uruchomienia nowej instancji, można korzystać z istniejącej pamięci podręcznej bez konieczności ponownego ładowania danych.
Wady
- Konieczne jest przejście przez sieć, co spowalnia dostęp do danych w porównaniu z pamięcią podręczną lokalną.
- Wymagany jest oddzielny serwer pamięci podręcznej, co zwiększa koszty infrastruktury.
- Koszty infrastruktury? → Opłaty za serwer, czas poświęcony na konfigurację i konserwację infrastruktury, planowanie zabezpieczeń przed awariami.
Co wybrałem?
W mojej obecnej firmie serwer aplikacji działa w oparciu o wiele instancji, ale zdecydowałem się na pamięć podręczną lokalną.
Główne powody to:
- Ilość danych do przechowywania w pamięci podręcznej wynosi około 40 000 rekordów, co przekłada się na około 4 MB pamięci.
- Potrzebowałem wysokiej wydajności odczytu danych związanych z płatnościami.
- Choć serwer Redis jest dostępny, dodanie do niego nowej pamięci podręcznej wiązałoby się z dodatkowymi kosztami infrastrukturalnymi.
Jak aktualizować pamięć podręczną?
Jeśli serwer aplikacji działa w oparciu o wiele instancji, a zastosowano pamięć podręczną lokalną, dane w pamięci podręcznej na każdej instancji mogą się różnić. Na przykład instancja A może przechowywać w pamięci podręcznej dane „1”, podczas gdy instancja B może przechowywać „2” po zmianie. Jeśli użytkownik wyśle żądanie do load balancera, instancja A i B mogą zwrócić różne wartości.
Dlatego należy skonfigurować automatyczne czyszczenie pamięci podręcznej na każdej instancji, aby pobierać dane z bazy danych RDB. W tym celu często stosuje się TTL.
Jak ustawić TTL?
TTL (Time To Live) to czas, po którym dane w pamięci podręcznej są usuwane. Na przykład, jeśli ustawimy TTL na 5 sekund, dane w pamięci podręcznej zostaną usunięte po 5 sekundach. Następnie, gdy wystąpi błąd pamięci podręcznej (cache miss), dane są pobierane z bazy danych RDB i zapisywane w pamięci podręcznej.
Jak więc ustawić TTL?
Operacje odczytu/zapisu wykonywane na jednym serwerze pamięci podręcznej
Jeśli operacje odczytu/zapisu są wykonywane na jednym serwerze pamięci podręcznej (np. Redis) lub na jednym serwerze aplikacji z pamięcią podręczną lokalną, wartość TTL może być długa, np. w jednostkach czasu. W końcu podczas zapisywania danych w pamięci podręcznej, te same dane są modyfikowane, a serwer, który pobiera dane z pamięci podręcznej, zawsze będzie miał dostęp do najnowszych danych.
W takim przypadku nie trzeba ustawiać TTL. Zamiast tego można skonfigurować serwer pamięci podręcznej tak, aby automatycznie usuwał dane z pamięci podręcznej według algorytmu LRU (Least Recently Used) w przypadku, gdy pamięć podręczna jest pełna.
Operacje odczytu/zapisu wykonywane na wielu serwerach pamięci podręcznej
Jeśli operacje odczytu/zapisu są wykonywane na wielu serwerach pamięci podręcznej (np. Redis) lub na wielu serwerach aplikacji z pamięcią podręczną lokalną, TTL należy ustawić na wartości w zakresie sekund lub minut. Istnieje bowiem ryzyko odczytania przestarzałych danych z serwera pamięci podręcznej, który nie został jeszcze zaktualizowany.
W tym przypadku wybór TTL zależy od wielu czynników. Im ważniejsze są aktualizacje i im większe prawdopodobieństwo zmiany danych, tym krótszy powinien być TTL. Im mniej ważne są aktualizacje i im mniejsze prawdopodobieństwo zmiany danych, tym dłuższy może być TTL.
Jak ustawiłem TTL?
Przechowywane przeze mnie dane są związane z płatnościami, a choć nie zastosowałem pamięci podręcznej do funkcji bezpośrednio odpowiedzialnych za przetwarzanie płatności, to ze względu na specyfikę płatności aktualizacje są kluczowe. Zmiany danych są jednak rzadkie, więc ustawiłem TTL na 5 sekund, co zapewnia bezpieczne rozwiązanie.
Podsumowanie
Podsumowując, moje rozwiązanie pamięci podręcznej wygląda następująco:
- Dane związane z płatnościami
- Bardzo częste odczyty, ale rzadkie aktualizacje.
- Zastosowanie pamięci podręcznej tylko w funkcjach, które nie są bezpośrednio związane z płatnościami, ale wykonują odczyty.
- Zastosowanie pamięci podręcznej lokalnej z TTL ustawionym na 5 sekund.
Kolejny krok to przeprowadzenie testów wydajnościowych dla zastosowanego rozwiązania. Na razie nie mam jeszcze konkretnego planu testów, ale opiszę je w następnym wpisie!