제이온

[DB] Kryteria konfigurowania pamięci podręcznej

  • Język oryginalny: Koreański
  • Kraj: Wszystkie krajecountry-flag
  • TO

Utworzono: 2024-04-25

Utworzono: 2024-04-25 22:24

Dzień dobry? Jestem Jayon.

Dzisiaj chciałbym wyjaśnić kryteria konfigurowania pamięci podręcznej. To wpis oparty na moim doświadczeniu w pracy, więc traktujcie go raczej jako inspirację ㅎㅎ


Czym jest pamięć podręczna?

Pamięć podręczna to mechanizm, który przechowuje wyniki przyszłych żądań, aby móc je szybko obsłużyć. Innymi słowy, przechowuje wyniki z góry, a gdy nadejdzie żądanie, zamiast odwoływać się do bazy danych (DB) lub interfejsu API, odwołuje się do pamięci podręcznej i przetwarza żądanie. Za powstaniem tego mechanizmu stoi zasada Pareto.

Zasada Pareto mówi, że 80% wyników jest generowanych przez 20% przyczyn. Dobrze jest zapoznać się z poniższym obrazkiem!


[DB] Kryteria konfigurowania pamięci podręcznej


Oznacza to, że nie ma potrzeby buforowania wszystkich wyników, a jedynie 20% najczęściej używanych, co pozwala na ogólną poprawę wydajności.


Jakie dane należy buforować?

Zgodnie z zasadą Pareto, nie należy buforować dowolnych danych, a jedynie te, które są naprawdę potrzebne. Jakie więc dane należy buforować?


Dane, które są często odczytywane, ale rzadko zapisywane

W teorii często mówi się, że „należy buforować dane, które są często odczytywane, ale rzadko zapisywane”, ale kryteria „częstego odczytu” i „rzadkiego zapisu” były dość niejasne.


Dlatego ja badam dane do buforowania w następujących krokach.


  • Za pomocą APM, takiego jak DataDog, sprawdzam 5 najczęstszych wywołań zapytań do RDB.
  • Wśród nich znajduję zapytania odczytu i sprawdzam, z jakiej tabeli są pobierane dane.
  • Sprawdzam, jak często wywoływane są zapytania aktualizujące daną tabelę.


W ten sposób sprawdzam, czy dane są często odczytywane, ale rzadko aktualizowane. W tabeli, którą sprawdziłem w praktyce, zapytania odczytu były wywoływane 1,74 miliona razy dziennie, a zapytania aktualizujące maksymalnie 500 razy. To idealne warunki do buforowania ㅎㅎ


Dane wrażliwe na aktualizacje

Dane wrażliwe na aktualizacje to takie, w których różnica między RDB a pamięcią podręczną musi być krótka. Na przykład w przypadku informacji związanych z płatnościami aktualizacja jest bardzo ważna, więc nawet jeśli spełnia powyższe warunki buforowania, należy rozważyć jej zastosowanie.


Musiałem zastosować buforowanie do tabel związanych z płatnościami, które spełniały oba powyższe warunki. Dlatego nie zastosowałem buforowania do wszystkich logik korzystających z tych tabel, ale zdecydowałem się na częściowe buforowanie w stosunkowo bezpiecznych logikach, w których płatności nie są wykonywane.


Buforowanie lokalne vs. globalne

Teraz już wiemy, jakie dane i w jakim zakresie należy buforować. Należy jednak zastanowić się, „gdzie” należy przechowywać buforowane dane. Zazwyczaj można je zapisywać w pamięci lokalnej lub na osobnym serwerze, takim jak Redis.


Buforowanie lokalne

Buforowanie lokalne polega na zapisywaniu buforowanych danych w pamięci serwera aplikacji. Często wykorzystuje się w tym celu biblioteki takie jak Guava Cache lub Caffeine Cache.


Zalety

  • Ponieważ podczas wykonywania logiki aplikacji można od razu odwoływać się do pamięci podręcznej na tym samym serwerze, jest to bardzo szybkie.
  • Łatwe w implementacji.


Wady

  • W przypadku wielu instancji pojawia się kilka problemów.


Buforowanie globalne

Buforowanie globalne polega na użyciu osobnego serwera do przechowywania buforowanych danych, takiego jak Redis.


Zalety

  • Ponieważ instancje współdzielą pamięć podręczną, zmiana pamięci podręcznej na jednej instancji jest odzwierciedlana na wszystkich innych instancjach.
  • Po uruchomieniu nowej instancji wystarczy, że będzie ona odwoływać się do istniejącego magazynu pamięci podręcznej, nie ma potrzeby ponownego ładowania danych.


Wady

  • Ponieważ konieczne jest przejście przez sieć, jest wolniejsze niż buforowanie lokalne.
  • Wymaga użycia osobnego serwera pamięci podręcznej, co generuje dodatkowe koszty infrastruktury.


Którą opcję wybrałem?

Obecnie serwer aplikacji mojej firmy działa w strukturze z wieloma instancjami, ale wybrałem buforowanie lokalne.

Główne powody to trzy.


  • Buforowanych danych w RDB jest nieco mniej niż 40 000, a załadowanie ich wszystkich do pamięci zajmuje mniej niż 4 MB.
  • Wymagana była wysoka wydajność odczytu danych związanych z płatnościami.
  • Chociaż Redis jest już dostępny, przechowywanie nowych danych w pamięci podręcznej w Redisie generuje dodatkowe koszty infrastruktury.


Jak aktualizować pamięć podręczną?

Jeśli serwer aplikacji ma wiele instancji, a zastosowano buforowanie lokalne, wartości pamięci podręcznej na każdej instancji mogą się różnić. Na przykład wartość danych w pamięci podręcznej na serwerze A może wynosić „1”, a na serwerze B „2”, ponieważ została zmieniona na serwerze B. W takiej sytuacji użytkownik wysyłający żądanie do load balancera otrzyma różne wartości z serwera A i B.


Dlatego należy skonfigurować automatyczne usuwanie pamięci podręcznej na każdej instancji i odwoływanie się do RDB w celu pobrania danych. W tym celu często stosuje się TTL.


Jaka powinna być wartość TTL?

TTL (Time To Live) to ustawienie automatycznego usuwania pamięci podręcznej po określonym czasie. Na przykład, jeśli ustawimy TTL na 5 sekund, dane w pamięci podręcznej zostaną automatycznie usunięte po 5 sekundach. Następnie, jeśli wystąpi chybione trafienie w pamięci podręcznej, dane zostaną pobrane z RDB i zapisane.

Jaka więc powinna być wartość TTL?


Odczyt/zapis na jednym serwerze pamięci podręcznej

Jeśli odczyt/zapis odbywa się na jednym serwerze pamięci podręcznej, takim jak Redis, lub na jednym serwerze aplikacji z włączonym buforowaniem lokalnym, wartość TTL może być większa niż jednostka czasu. I tak podczas zapisu zostanie zaktualizowana istniejąca pamięć podręczna, a serwer pobierający dane z tej pamięci podręcznej zawsze będzie otrzymywał zaktualizowane dane.


W takim przypadku można nie ustawiać TTL, a jedynie skonfigurować automatyczne usuwanie części pamięci podręcznej za pomocą algorytmu LRU, gdy pamięć podręczna jest pełna.


Odczyt/zapis na wielu serwerach pamięci podręcznej

Jeśli odczyt/zapis odbywa się na wielu serwerach pamięci podręcznej lub na wielu serwerach aplikacji z włączonym buforowaniem lokalnym, lepiej ustawić TTL na sekundy lub minuty. Dzieje się tak, ponieważ istnieje ryzyko odczytania nieaktualnych danych z serwera pamięci podręcznej, który jeszcze nie odzwierciedla zmian.


Wartość TTL zależy od różnych kontekstów. Im ważniejsza jest aktualizacja i większe prawdopodobieństwo zmiany wartości, tym krótszy powinien być TTL. Im mniej ważna jest aktualizacja i mniejsze prawdopodobieństwo zmiany wartości, tym dłuższy może być TTL.


Jak ustawiłem TTL?

Buforowane przeze mnie dane dotyczą płatności, a nawet jeśli nie zastosuję buforowania do ścisłych logik przetwarzania płatności, to ze względu na charakter płatności aktualizacja jest ważna. Jednak prawdopodobieństwo aktualizacji jest niskie, więc dla bezpieczeństwa ustawiłem TTL na 5 sekund.


Podsumowanie

Podsumowując, wybrany przeze mnie sposób buforowania wygląda następująco:


  • Dane dotyczące płatności
  • Bardzo częste odczyty, ale rzadkie aktualizacje.
  • Buforowanie zastosowane tylko w logikach, w których płatności nie są wykonywane, ale występują odczyty.
  • Zastosowano buforowanie lokalne z TTL ustawionym na 5 sekund.


Następnym krokiem jest przeprowadzenie testów wydajności dla wdrożonego sposobu buforowania. Nadal zastanawiam się, jak dokładnie przeprowadzić testy wydajności, więc opiszę to w kolejnym wpisie!

Komentarze0

[Dla osób bez informatycznego wykształcenia, jak przetrwać jako programista] 14. Podsumowanie często zadawanych pytań na rozmowach kwalifikacyjnych dla początkujących programistówPodsumowując, przedstawiamy często zadawane pytania techniczne na rozmowach kwalifikacyjnych dla programistów (obszar pamięci, struktury danych, bazy danych itd.). Mamy nadzieję, że pomoże to w przygotowaniach do rozmowy kwalifikacyjnej.
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

April 3, 2024