Cachowanie w PHP

Wraz ze wzrostem popularności naszego serwisu, kiedy dzienna liczba odwiedzających to nie 100 a 10 000 osób, zapotrzebowanie serwera na zasoby rośnie. Najczęściej jesteśmy wtedy zmuszeni do zakupienia lepszego, bardziej wydajnego serwera. Z pomocą może przyjść nam cachowanie, z którego możemy skorzystać na kilka różnych sposobów.

Na początek, czym jest cachowanie?
Najprościej możemy je opisać jako tymczasowe zapisanie danych w pamięci na później, do ponownego wykorzystania, dzięki czemu zyskujemy na wydajności strony.

W PHP możemy skorzystać z kilku sposobów zapisu danych na później, które przybliżę Wam w tym wpisie.

1. Cachowanie zawartości

Pierwszym z nich jest cachowanie zawartości. Załóżmy, że posiadamy serwis z ogłoszeniami, gdzie każde z naszych ogłoszeń posiada jakąś treść dodaną przez użytkownika. Gdy użytkownik odwiedza naszą stronę, skrypt pobiera odpowiednie dane z bazy, generuje kod HTML i wyświetla go użytkownikowi. Ponieważ treść ogłoszenia zmienia się bardzo rzadko lub wcale, możemy cały gotowy wygenerowany kod HTML zapisać do pliku na dysku naszego serwera. Zamiast kilku wcześniej opisanych kroków, pobieramy wygenerowany kod z pliku i wyświetlamy go użytkownikowi. W efekcie nasza strona ładuje się szybciej.

Należy tutaj pamiętać o jednej bardzo ważnej rzeczy. Projektując cachowanie, musimy dodać funkcjonalność, która usunie cache w sytuacji, gdy znajdujące się w nim dane ulegną zmianie. Wobec tego, gdy użytkownik zmieni treść swojego ogłoszenia, musimy usunąć cache, aby mógł się zaktualizować o nowe dane. Najłatwiejszym sposobem na pobranie gotowego kodu HTML jest przypisanie go do zmiennej lub skorzystanie z tzw. output buffering czyli narzędzia pozwalającego nam „złapać” dane zanim zostaną przesłane do przeglądarki.

2. Cache w pamięci RAM

Kolejną opcją, z jakiej możemy skorzystać jest cache w pamięci RAM. Jest to zdecydowanie najszybsze rozwiązanie, ponieważ prędkość transferu danych z i do pamięci jest dużo większa niż prędkość dysku, nawet jeśli posiadamy dysk SSD. Nie jesteśmy w stanie z poziomu PHP dostać się bezpośrednio w łatwy sposób do pamięci, ale z pomocą przychodzą nam rozszerzenia, najczęściej już wbudowane w PHP.

OpCache

OpCache to rozszerzenie, znajdujące się w każdej wersji PHP od 5.5.0. Możemy użyć go w wersjach wcześniejszych, ale konieczna jest jego instalacja ręczna. Każdy skrypt podczas uruchamiania jest przekazywany do kompilatora, który następnie wykonuje zawarte w nim instrukcje. OPC zapisuje w pamięci wstępnie skompilowany kod, dzięki czemu kompilacja następuje tylko jeden raz i przy kolejnym uruchomieniu tego samego skryptu, wykorzystywana jest wersja prekompilowana – kod maszynowy zrozumiały dla serwera. Jest to bardzo przydatne rozwiązanie, gdy posiadamy dużo plików w naszej aplikacji.

Memcached

Memcached jest kolejnym rozwiązaniem, wykorzystującym pamięć RAM. W tym wypadku konieczna jest instalacja serwera, z którym połączymy się za pomocą naszego skryptu. Rozwiązanie to nie ogranicza nas co do ilości serwerów, które możemy łączyć w klastry a każdy z nich może przechowywać dane z konkretnej grupy. Pamiętać musimy tutaj o odpowiednim zabezpieczeniu dostępu do serwerów, zwłaszcza jeśli znajdują się one na innych maszynach fizycznych.

Dane na serwerze memcached są przechowywane jako pary klucz-wartość, gdzie maksymalna wielkość klucza to 250 bajtów, a wielkość przechowywanych danych to 1MB. Dodatkowo dane mogą mieć ustawiony czas ważności, po którym automatycznie zostaną usunięte z cache. Nie jest również rozróżniany typ przechowywanych danych, ważne aby były one pre-serializowane.

Dla każdego serwera możemy ustawić, jaka ilość danych zostaje mu przydzielona i w przypadku jej przekroczenia, najstarsze wpisy są automatycznie usuwane. Korzystając z memcache należy więc mieć na uwadze, że dane, których oczekujemy mogą, ale nie muszą znaleźć się w cache i tak zaprojektować skrypt, aby najpierw sprawdzał ich istnienie.

Redis

Rozwiązaniem najbardziej rozbudowanym, lecz zapewniającym największą stabilność jest Redis – system open source. Podobnie jak memcached jest on zaliczany do grupy NoSQL systemów przechowywania danych. Przechowuje on wartości w parach klucz-wartość, a dane są przechowywane w pamięci RAM. Często nazywany jest on jako „memcached na sterydach”, posiada on zdecydowanie lepsze zarządzanie pamięcią, co za tym idzie, jest wydajniejszy. Przechowywane dane mogą mieć maksymalny rozmiar aż 512MB.
Na plus należy również zaliczyć ogromną ilość wbudowanych komend i kilka podstawowych struktur danych wbudowanych w Redis’a.

Zdecydowanie szybciej obsłuży on tzw. rozgrzewanie cache (czyli automatyczne zapisywanie cache przed uruchomieniem strony), co przy serwisach o dużym ruchu ma ogromne znaczenie. Podobnie jak w memcached mamy możliwość zdefiniowania kilku serwerów, które mogą być ze sobą połączone i replikować dane, czego w przypadku memcached nie jesteśmy w stanie osiągnąć, gdyż tam każdy serwer „żyje swoim życiem”. Jego obsługa nie jest niestety wbudowana w PHP, ale możemy skorzystać z szeregu bibliotek, które ułatwią z nim pracę, gdzie do najpopularniejszych należy Predis.

3. MySQL cache

Na koniec, rozwiązanie, z którego często początkujący użytkownicy korzystają zupełnie nieświadomie, mianowicie MySQL cache czyli cachowanie zapytań kierowanych do bazy danych. W tym przypadku przechowywane są wyniki zapytań SELECT, gdzie obsługą tego procesu zajmuje się serwer bazy danych. Wystarczy, iż w konfiguracji serwera poinformujemy go, że chcemy korzystać z cache, a serwer zajmie się całą resztą.
To rozwiązanie powoduje przy kolejnych identycznych zapytaniach, dużo szybsze zwracanie danych.

Oto kilka rzeczy, o których musimy pamiętać w przypadku MySQL cache:

  • Działa jedynie dla zapytań SELECT
  • Zapytania muszą być identyczne
  • Nie działa dla prepared statements
  • Zapytanie jest przechowywane wraz z danymi jakie zwróciło
  • W przypadku dodania nowego rekordu do tabeli cache zostanie automatycznie oznaczony jako nieaktualny i ponownie pobrany przy kolejnym zapytaniu select.

Podsumowując, cache służy nam do przechowywania danych, które nie zmieniają się często i mogą być wykorzystane ponownie. Dla danych, w przypadku których dochodzi do zmian, zdecydowanie zalecaną metodą jest skorzystanie z opcji przechowującej dane w pamięci RAM, pamiętając, aby nasz skrypt sprawdzał, czy dane istnieją w cache i nie traktował jako pewnik, że się tam znajdują. Większość, jeśli nie wszystkie, popularnych frameworków ma wbudowaną obsługę różnych metod cachowania, a do nas należy jedynie uzupełnienie danych konfiguracyjnych.

Cachowanie nie nadaje się do przechowywania wyników wyszukiwania, zwłaszcza na dużych ilościach rekordów oraz danych przesyłanych w czasie rzeczywistym.
Zawsze, do każdego przypadku musimy podejść indywidualnie i zdecydować czy cache w konkretnej sytuacji pomoże, czy tylko nie zaszkodzi.

Site Footer

Sliding Sidebar