Moja implementacja "keszu" |
Moja implementacja "keszu" |
23.02.2016, 10:13:40
Post
#1
|
|
Grupa: Zarejestrowani Postów: 111 Pomógł: 1 Dołączył: 24.12.2013 Ostrzeżenie: (0%) |
Witam,
Chcialbym dzis pdozielic sie swoim kolejnym wynalazkiem - obsluga keszu. Jest to co prawda dopiero zalazek tego co chce zrobic, albowiem brakuje metod odpowiedzialnych za obsluge danych, niemniej sposob 'komunikacji' ze sterownikiem widac na przykladzie metody Cache::dumpCache(); Docelowo zamierzam napisac takze wiecej sterownikow, zapewniajac dostep do: APC, eAccelerator, Dummy, File, MemCache, SQLite, WinCache, XCache. Zastanawiam sie takze nad mozliwoscia przechowywania keszu w cookies. Jednoczesnie prosze o ocene oraz komentarze - czyli ogolnie mowiac code review Jestem otwarty na wszelkie sugestie i uwagi poparte jakimkolwiek argumentem. Pozdrawiam serdecznie.
|
|
|
23.02.2016, 11:14:06
Post
#2
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%) |
Robisz to dla treningu czy do użytku?
Jest tyle gotowych klas do cache że głowa mała. |
|
|
23.02.2016, 11:19:34
Post
#3
|
|
Grupa: Zarejestrowani Postów: 111 Pomógł: 1 Dołączył: 24.12.2013 Ostrzeżenie: (0%) |
Oba powody sa poprawne. Przede wszystkim chce sie czegos nauczyc, pocwiczyc, nabrac wprawy.
Przy okazji chcialem takze stworzyc wlasny framework, ktory pozniej moglbym wykorzystac. Nie zalezy mi na poznawaniu gotowych rozwiazan, mimo ze sa sprawdzone i powszechnie stosowane. Nie planuje bowiem wykorzystywac nabytych umiejetnosci w celach zawodowych. PHP traktuje raczej jako hobby. Gdyby bylo inaczej, to mialbym certyfikat Zenda a nie RHCE ;-) Ten post edytował q.michal 23.02.2016, 11:31:18 |
|
|
27.02.2016, 08:12:05
Post
#4
|
|
Grupa: Zarejestrowani Postów: 88 Pomógł: 12 Dołączył: 17.09.2014 Skąd: Krasnystaw Ostrzeżenie: (0%) |
Cache w cookies? To ma jakiekolwiek praktyczne zastosowanie? Rozumiem że sesje, Kohana ma np. taki driver ale żeby cache? File driver jest pewnie w każdym frameworku domyślny ale jest to jedna z najwolniejszych metod. Oprócz tych driverów co je tu wymieniłeś są jeszcze Redis, SSDB, MongoDB i jeszcze nie wiadomo jakie bazy Nosql.
Ale co do FileDriver, to jest tak rozwiązane, że nazwy plików są jako md5 albo SHA1 na podstawie klucza, natomiast jest jeszcze ważna sprawa, pliki o nazwach md5 albo SHA1 są zapisywane nie tylko w tym katalogu gdzie przechowujesz cache ale jeszcze w odpowiednich podkatalogach dwuliterowych, gdzie ich nazwy to dwa pierwsze znaki w nazwach md5 albo SHA1 a nie tak żeby wszystkie pliki były w tym samym katalogu. Stworzenie własnego frameworka wymaga dużej wiedzy. Prędzej się nauczysz jak przejrzysz dobrze kod Kohany (bo ten FW ma też takie rozwiązanie i różne drivery do cache, tworzone jako singletony) i zobacz jak to tam jest rozwiązane. Będziesz pewnie to tworzył przez kilka mies. albo i więcej, pytanie co takiego osiągniesz? No chyba że Twój FW powali na kolana Symfony2 albo Laravel |
|
|
27.02.2016, 12:32:15
Post
#5
|
|
Grupa: Zarejestrowani Postów: 111 Pomógł: 1 Dołączył: 24.12.2013 Ostrzeżenie: (0%) |
Jak to mowia, takie hobby ;-)
Przyznam szczerze ze nie rozumiem idei wrzucania plikow cache do podkatalogow, jak to opisales daro0. Jaki jest sens takiego segregowania? Na szybko napisalem driver do obslugi cache bazujacego na plikach. Poniewaz wielokrotnie trzeba wyliczyc sumy MD5 zdecydowalem sie przechowywac je dodatkowo w tablicy:
Wszelkie sugestie mile widziane Ten post edytował q.michal 27.02.2016, 12:32:30 |
|
|
27.02.2016, 12:48:23
Post
#6
|
|
Grupa: Zarejestrowani Postów: 88 Pomógł: 12 Dołączył: 17.09.2014 Skąd: Krasnystaw Ostrzeżenie: (0%) |
Też na początku się zastanawiałem po co te podkatalogi ale jak przejrzałem to co jest w źródłach Kohana Core, tutaj chodzi mi o statyczną funkcję Kohana::cache to tam jest wyjaśnione, że chodzi o zapobieganie przeciążeniu systemu plików. No bo co sie stanie gdy masz gdzieś koło miliona plików w jednym katalogu?
https://kohanaframework.org/3.1/guide/api/Kohana_Core#cache ten fragment:
Laravel ma jeszcze bardziej podzielone, tj. podkatalogi of 00 do ff czyli 2 pierwsze litery z nazw plików cache (md5) a w nich jeszcze znowu podział na podkatalogi w ten sam sposób czyli kolejne dwa znaki na bazie nazwy plików cache. Ten post edytował daro0 27.02.2016, 12:50:00 |
|
|
27.02.2016, 12:57:35
Post
#7
|
|
Grupa: Zarejestrowani Postów: 111 Pomógł: 1 Dołączył: 24.12.2013 Ostrzeżenie: (0%) |
Brzmi sensownie, ale tez we wszystko bym bezgranicznie nie wierzyl. Nie mowie teraz konkretnie o tych podkatalogach, jednak jak widze pare linijek nizej chmod 777, to od razu na mysl przychodzi mi potencjalna luka w bezpieczenstwie
Niemniej jednak przekonales mnie do idei stosowania podkatalogow. W wolnej chwili naniose poprawki i rozbuduje kod. BTW: Co sadzisz o globalnej serializacji? Tj. zastanawiam sie czy warto wszystko serializowac, bez wzgledu na wartosc oraz typ zastosowanego cache? |
|
|
27.02.2016, 13:11:00
Post
#8
|
|
Grupa: Zarejestrowani Postów: 88 Pomógł: 12 Dołączył: 17.09.2014 Skąd: Krasnystaw Ostrzeżenie: (0%) |
Co do serializacji to też chyba nie jest takie proste:
http://techblog.procurios.nl/k/news/view/3...var_export.html Kolejna sprawa, nie za bardzo rozumiem to w Kohanie np:
Natomiast jest też moduł cache zamiast standowego Kohana:cache https://kohanaframework.org/3.1/guide/api/Cache_File#set I nie mogę załapać dlaczego w Kohana Core jest blokada LOCK_EX a w tym module File_Cache nie ma tzn. jest tak:
Ta blokada jest w ogóle pod Linux wymagana czy nie? Co do Twojego przykładu, pomyśl jeszcze o odśmiecaniu (GarbageCollector), tak żeby co jakiś czas usuwać niepotrzebne i wygasłe pliki np. w taki sposób:
To co jakiś 10 request wywali niepotrzebne już pliki. |
|
|
27.02.2016, 13:21:49
Post
#9
|
|
Grupa: Zarejestrowani Postów: 111 Pomógł: 1 Dołączył: 24.12.2013 Ostrzeżenie: (0%) |
Ciekawe zestawienie. Watpie jednak, aby ktos pakowal tak duze porcje danych do cache. Sporo interpreterow ma limit pamieci ustawiony na 64-128MB AFAIK. Wynika wiec z tego ze musialbys wsadzic (niemal) caly skrypt do cache.
Pytajac o serializacja bardziej oabwialem sie narzutu pamieci/CPU niezbednego na wykonanie serializacji przy zapisie i deserializacji przy odczycie. Z tego benchmarku wynika jednak, ze to nie powinno byc problemem. Lockowanie ma ta zalete, ze inny watek (request) nie nadpisze Ci tych danych. Teoretycznie istnieje ryzyko, ze 2 requesty odpalone w tym samym czasie beda chcialy cos zapisac do tego pliku i wtedy jego zawartosc moze byc inna niz sie tego spodziewasz. Exclusive lock sprawia, ze inny watek nie bedzie w stanie sie w miedzyczasie dokleic do pliku i uwazam ze warto to dopisac. Sam zreszta stosuje tego locka Przemysle odsmiecanie, choc nie jestem teraz pewien czy we wszystkich magazynach da sie to osiagnac i jaki bylby narzut. Jezeli chodzi o pliki, to trzeba byloby sie przeiterowac po wszystkich istniejacych plikach, zaladowac je, sprawdzic czy nie wygasly i ew usunac. Musialbym jeszcze sprawdzic czy np. APC oferuje taka mozliwosc. |
|
|
27.02.2016, 14:53:23
Post
#10
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%) |
Zawsze możesz stworzyć "tablicę" file cache, która będzie trzymała hash i czas pliku, a potem tylko przefiltrować tablicę i usunąć pliki.
|
|
|
27.02.2016, 14:59:36
Post
#11
|
|
Grupa: Zarejestrowani Postów: 111 Pomógł: 1 Dołączył: 24.12.2013 Ostrzeżenie: (0%) |
|
|
|
27.02.2016, 15:20:44
Post
#12
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%) |
Musisz ją zapisać. Wydało mi się to logiczne.
Ten post edytował Pyton_000 27.02.2016, 15:20:58 |
|
|
27.02.2016, 17:19:17
Post
#13
|
|
Grupa: Zarejestrowani Postów: 88 Pomógł: 12 Dołączył: 17.09.2014 Skąd: Krasnystaw Ostrzeżenie: (0%) |
O jakich tablicach Wy w ogóle piszecie? Nic takiego się w praktyce nie wykorzystuje W praktyce najprostszy cache polega na zapisaniu serializowanych danych (tutaj można zapisywać do cache cokolwiek) do pliku w okreslonym katalogu cache z nazwą jako md5 dla tego co zapisujecie do cache (klucz), natomiast przy odczycie ważność cache sprawdzana jest przez porównanie czasu ostatniej modyfikacji pliku za pomocą filemtime() z aktualnym czasem pobranym za pomocą time(), czas ten jest liczony w sekundach, po prostu odejmuje się time() od filemtime() i jesli to jest mniejsze niż ustalony czas życia ttl, cache jest jeszcze ważna, po upływie tego czasu już należy pobrać dane na nowo i zapisac do cache.
Oczywiście należy też uwzględnić obsługę wyjątków, jak się wywali (jakiś błąd deserializacji) to też można przyjąć że cache jest nieprawidłowe i się znowu pobiera coś z bazy albo jakieś inne dane i znowu zapisuje. Oczywiście te pliki które fizycznie zostaną a upłynął czas życia wynikający z tego porównania należałoby usunąć, robi się to albo za pomocą cron-a, albo probalilistycznie, przy założeniu że wykona się to biorąc pod uwagę ilość odwiedzin. Prawdopodobieństwo można sobie ustalić np. na 1%. A te Wasze tablice to też należałoby zapisywać do cache, żeby Wam nie zniknęły te dane, więc jak Wy sobie to wyobrażacie? I tak File Store jest jednym z najwolniejszych sposobów a Wy jeszcze macie zamiar to spowalniać zapisując serializowane tablice asocjacyjne o nie wiadomo jakiej ilości elementów? A to trzeba za każdym razem i deserializować i odczytywać a potem zapisywać. Pytanie po co? |
|
|
27.02.2016, 19:10:06
Post
#14
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%) |
@daro0 To oświeć mnie jak zapiszesz obiekt do Cache? Bo ja ostatnio walczyłem z FileStorage i co nie co musiałem się pogłowić żeby to sprawnie działało.
Co do tablicy to owszem, można zapuścić CRON który będzie czyścił pliki nie ważne, ale i tak musisz napisać taki mechanizm. A jeśli będziesz miał 1mln plików w podkatalogach to przelecenie wszystkich plików i sprawdzanie który przypadkiem jest przeterminowany to bzdura totalna. Dla tego moja propozycja z tablicą cache. 1 funkcja i masz listę plików które trzeba wywalić, i nie trzeba latać po katalogach i mordować I/O dysku. Tak FileStorage to najwolniejszy z silników (cache nawet nie wspominam bo to się nie nadaje). |
|
|
27.02.2016, 19:48:46
Post
#15
|
|
Grupa: Zarejestrowani Postów: 88 Pomógł: 12 Dołączył: 17.09.2014 Skąd: Krasnystaw Ostrzeżenie: (0%) |
Tak w dużym uproszczeniu:
W czym tu jest problem? Zserializuje całą klasę jako string a po deserializacji zwróci te dane jako obiekt. Co do odśmiecania, dlatego wydaje mi się że ten typ cache jest do małej ilości ruchu na stronie. Tak przelecieć podkatalogi trzeba by rekurencyjnie i wszystko sprawdzać. CRON podałem tylko jako przykład, natomiast czemu nie użyć odśmiecania w oparciu o random numbers? Któryś z użytkowników wejdzie na stronę i GC zadziała A sesje to niby jaki mają mechanizm? Przecież też działa probalilistyczny garbage collector. I też przecież można by teoretycznie tworzyć miliony sesji bo jest kilka milionów użytkowników i co wtedy? Chyba podobnie. |
|
|
27.02.2016, 19:53:35
Post
#16
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%) |
Ja wiem że trzeba obiekt zserializować.
Ale... Chcesz to robić po stronie użytkownika? Bez sensu, dodasz serializację wszystkich danych w cachce? Też bez sensu. Dasz serializację obiektów a potem unserialize dla wszystkich danych? Też bez sensu (wywalla błędy). Rozwiązanie które użyłem to serializowanie tylko obiektów, i przy odczycie sprawdzanie czy string jest ciągiem zserializowanym (by regex) i jeśli tak to zrób unserialize. Co do random number, to tak, 1% i odpala się GC. Ale żeby nie zabijać tym usera właśnie po to jest tablica cache. |
|
|
27.02.2016, 21:32:28
Post
#17
|
|
Grupa: Zarejestrowani Postów: 111 Pomógł: 1 Dołączył: 24.12.2013 Ostrzeżenie: (0%) |
Odnoszac sie do benchmarku zalaczonego przez daro0, mysle ze serializacja wszystkich danych wcale nie jest takim zlym pomyslem. Narzut wydaje sie byc znikomy, a raczej malo kto keszuje kilkudziesiecio megabajtowe dane. Poza tym to wiele upraszcza i nie trzeba pozniej sprawdzac czy potrzebna jest deserializacja czy nie. Poprostu wszystkie dane z gory traktujemy tak samo. Potencjalnie rozwiazuje to takze bugi, np. moze zwrocic zserializowanego NULLa zamiast NULLa, tak wiec konstrukcja if(!$zmienna) zadziala inaczej.
Osobiscie myslalem nad zrobieniem GC bardziej przewidywalnym i np keszowaniem ostatniego czasu wykonania GC. Po czym ustalic np. czas jego wykonania co godzine. Tak, wiec GC wykonywaloby sie nie czesciej niz raz na godzine, ew rzadziej w zaleznosci od ruchu na stronie. Jest to bardziej przewidywalne, niz probabilistyka. Random moze wygenerowac kilka razy z rzedu ta sama liczbe, albo przez tydzien w ogole jej nie wygenerowac. |
|
|
28.02.2016, 07:37:29
Post
#18
|
|
Grupa: Zarejestrowani Postów: 88 Pomógł: 12 Dołączył: 17.09.2014 Skąd: Krasnystaw Ostrzeżenie: (0%) |
To rand(0,99) jest chyba niezbyt dokładne. Można jeszcze użyć mt_rand, natomiast jakie jest prawdopodobieństwo że się trafi kilka razy pod rząd ta sama liczba? Tu zakładam że generator jest dość dobry a nie jakiś pseudo generator. Poza tym na ile jest prawdopodobne że się w katalogu cache utworzy ileś tam milionów plików a jeżeli nawet to ile one zajmują?
Weźmy np. jakieś API i pobieranie kursów walut jako JSON. Pobieranie ostatnich notowań kursów walut, oczywiście bez sensu to wywoływać za każdym razem, zwłaszcza że tu notowania są co dzień więc cache można sobie ustawić nawet na 24h. Nawet jak ktoś zechce szukać z różnymi opcjami to ile tu się tych plików utworzy? Jakiś użytkownik poczeka sobie może z 2 sekundy, reszta użytkowników będzie miała dane z cache i tu będzie ułamek sekundy, więc w czym tu jest problem? Ten post edytował daro0 28.02.2016, 07:39:46 |
|
|
29.02.2016, 16:13:24
Post
#19
|
|
Grupa: Zarejestrowani Postów: 111 Pomógł: 1 Dołączył: 24.12.2013 Ostrzeżenie: (0%) |
Raczej malo trafiony przyklad
Dane pobierzesz, przeparsujesz i zapiszesz raz, obliczasz sobie pozniej dowoli. Funkcja touch() pozwala ustawic modified time w przyszlosci. Co prawda w przyszlosc mozna wybiec jedynie o ok 11 dni, ale zawsze cos. Tak wiec po utworzeniu pliku zawierajacego dane, mozna mu zmienic mtime na time() + $ttl. Nie ma pozniej potrzeby zapisywania czegokolwiek do keszu. Trzeba poprostu przeleciec sie po plikach, sprawdzic ich mtime i jezeli sa starsze niz aktualny timestamp, to wywalic do kosza ;-) Moze to generowac I/O, ale z cala pewnoscia mniejsze niz ladowania calego pliku do pamieci, deserializacja obiektu i sprawdzanie jego TTL. Poza tym, jezeli ktos buduje duzy serwis, to nie postawi go raczej na hostingu wspoldzielonym, tylko VPS czy wrecz dedyk. A tak bedzie mozliwosc skorzystania z bardziej zaawansowanych metod keszowania - np. Redis. Najnowsza wersja z plikowym sterownikiem: http://wklej.org/hash/443ec12d749/ Ten post edytował q.michal 29.02.2016, 16:17:44 |
|
|
Wersja Lo-Fi | Aktualny czas: 22.09.2024 - 18:25 |