Temat: W jaki sposób cache'ować wyniki na stronie gdzie wynik...

W jaki sposób cache'ować wyniki na stronie gdzie wynik jest uzależniony od parametru GET?
Czym rozwiązać taki problem aby strona nie wczytywała się +/- 4 sekund, tylko jakoś szybciej?

Z góry dziękuję za odpowiedzi
Krzysztof N.

Krzysztof N. CEO. Aplikacje
internetowe i
mobilne. Symfony,
Zend.

Temat: W jaki sposób cache'ować wyniki na stronie gdzie wynik...

Tomasz K.:
W jaki sposób cache'ować wyniki na stronie gdzie wynik jest uzależniony od parametru GET?
Czym rozwiązać taki problem aby strona nie wczytywała się +/- 4 sekund, tylko jakoś szybciej?

Z góry dziękuję za odpowiedzi
Cache po stronie aplikacji.
Janusz Skudrzyk

Janusz Skudrzyk Członek zarządu,
weblabs.pl

Temat: W jaki sposób cache'ować wyniki na stronie gdzie wynik...

Przed wprowadzeniem cache proponuję naprawić zapytania do bazy. Być może nawet cache nie będzie potrzebny.

Hint:
1. explain
2. log_slow_queries = /sciezka/mysql-slow.log
long_query_time = 1 (chyba, że patch od percony, wtedy można dać czas po przecinku)
log-queries-not-using-indexes
Tomasz Zadora

Tomasz Zadora programuję

Temat: W jaki sposób cache'ować wyniki na stronie gdzie wynik...

Janusz:

...a skąd automatyczne założenie, że baza to MySQL?

konto usunięte

Temat: W jaki sposób cache'ować wyniki na stronie gdzie wynik...

Tomasz przy takim pytanie odpowiedź to : "zależy" :-)

Chcesz cachować całe widoki czy tylko wyniki z bazy ? - musisz znaleźć gdzie w aplikacji masz wąskie gardło.

Możesz wspomóc się memcached albo bazą Redis - tworzysz sobie klucze z tym parametrem ( z GET) id odpowiednio przypisujesz im wartość , ustawiasz limit pamięci jaki może zając cache i jeżeli klucz nie jest zbyt często używany a limit się kończy to wylatuje ( tak w uproszczeniu ). No ale musisz mieć dostęp do "serwera"
Jeżeli to zwykły hosting to cachowaniu do plików - minus, że musisz tym jakość zarządzać

A może czas wczytywania strony nie leży po stronie backendu - sprawdź ile masz zewnętrznych odwołań przy wczytywaniu strony / request ( sprawdź czas ) . Czasami warto zrobić jeden większy plik (css, js) niż odwoływać się do 10.
Tomasz Zadora

Tomasz Zadora programuję

Temat: W jaki sposób cache'ować wyniki na stronie gdzie wynik...

Ja robię to tak, że keszuję wynik działania jakiejś funkcji/metody w postaci np.:



public function getProductList($categoryId, $useCache = true, $cacheTime = 300) {


if ($useCache) {

$cacheManager = \DependencyInjector::get('CacheManager');
$key = 'getProductList_'.$categoryId;
$result = $this->getProductList($categoryId, false);
return $cacheManager->getOrSetCache($result , $key, $cacheTime );

}


....kod pobierający listę produktów - np. przez zapytanie SQL....

return $productList;
}



I to wszystko - bardzo uniwersalny mechanizm, można tym keszować niemal wszystko, nie ważne czy dane pochodzą z SQL czy np. usługi SOAP.

W przykładzie $categoryId może pochodzić z parametru GET

$cacheManager to oczywiście manager keszowania i można go sobie samemu napisać albo skorzystać z jakiegoś gotowego.

Metoda managera "getOrSetCache" zawsze zwraca rezultat z keszu, jeżeli w keszu nie ma rezultatu albo jest przeterminowany to przed zwrotem go do tego keszu wsadza.

Co więcej, taki mechanizm jest całkowicie transparentny dla zewnętrznego kodu uruchamiającego metodę.Ten post został edytowany przez Autora dnia 11.09.15 o godzinie 16:03

konto usunięte

Temat: W jaki sposób cache'ować wyniki na stronie gdzie wynik...

Tomasz Z.:
Metoda managera "getOrSetCache" zawsze zwraca rezultat z keszu, jeżeli w keszu nie ma rezultatu albo jest przeterminowany to przed zwrotem go do tego keszu wsadza.

Co więcej, taki mechanizm jest całkowicie transparentny dla zewnętrznego kodu uruchamiającego metodę.

pozwolisz, ale metoda "getOrSetCache" ? - przecież 99% z nas będzie szukało DocBlocka do niej ;-) i przy "generowaniu" $result wywołujesz ponownie tą samą metoda ?

gdyby Twój "CacheManager" implementował choćby to :

interface CacheInterface {
/**
* @return null|value
*/
public function get($key);
public function set($key, $val, $time);
}

to moim skromnym zdaniem tak będzie bardziej czytelne :

public function getProductList($categoryId, $useCache = true, $cacheTime = 300) {

$key = 'getProductList_'.$categoryId;
// to też bym inaczej zrobił ale niech będzie
$cacheManager = \DependencyInjector::get('CacheManager');
if ($useCache) {
if( null !== $cacheVal = $cacheManager->get($key) ) {
return $cacheVal;
}
}

$result = ....kod pobierający listę produktów - np. przez zapytanie SQL....

$cacheManager->set($key, $result, $cacheTime);

return $result;

}
Ten post został edytowany przez Autora dnia 12.09.15 o godzinie 08:37
Tomasz Zadora

Tomasz Zadora programuję

Temat: W jaki sposób cache'ować wyniki na stronie gdzie wynik...

Kolego Cieciński,

nie chce mi się za bardzo rozpisywać więc tylko zwrócę uwagę na jedną rzecz:

pomyślałeś w ogóle o czymś takim jak synchronizacja wielowątkowa? Wiesz co to jest programowanie wielowątkowe?

Twój sposób keszowania jest typowy, większość "programistów" tak robi. To się sprawdzi ale na stronie która ma mały ruch.

Pomyślałeś w ogóle co się dzieje jeżeli tworzenie zasobu który ma podlegać keszowaniu trwa bardzo długo np. 10 sekund, i jest zasobożerne, a masz np. 10-20 requestów na sekundę, co wcale nie jest tak dużo w godzinach szczytu np. w popularnym sklepie internetowym?

W takiej sytuacji, bez żadnej synchronizacji w ciągu 10 sekund masz 100-200 razy wykonaną tą metodę i 100-200 razy zasób wstawiony do keszu, a chyba nie o to chodzi?

Korzystając tylko z jednej metody getOrSetCache, przekazujesz do tej metody/managera cały problem synchronizacji i on może to zrealizować w ten sposób, że czasochłonna i potencjalnie zasobożerna metoda będzie wykonana tylko raz a wszystkie pozostałe requesty HTTP będą uśpione i będą się budzić np. co 1/10 sek aby sprawdzić czy metoda już została wykonana.

PHP już od dłuższego czasu jest bogate w co najmniej kilka dobrych sposobów na synchronizację tego typu rzeczy.

EODTen post został edytowany przez Autora dnia 12.09.15 o godzinie 17:48



Wyślij zaproszenie do