2012-02-05 18 views
6

APC pozwala przechowywać dane wewnątrz klawiszy, ale nie można grupować tych kluczy.Grupy kluczy z pamięcią podręczną APC

Więc jeśli chcę mieć grupę o nazwie "artykuły", a wewnątrz tej grupy będę miał klucze, które przyjmą formę ID artykułu Nie mogę tego łatwo zrobić.

articles -> 5 -> cached data 
     -> 10 -> cached data 
     -> 17 -> cached data 

     ... 

mogłem prefiks klucz z nazwą „grupa”, takich jak:

article_5 -> cached data 
article_10 -> cached data 
article_17 -> cached data 

... 

Ale to sprawia, że ​​nie da się usunąć całą grupę, jeśli chcę :(

sprawnego rozwiązaniem byłoby przechowywanie tablic wielowymiarowych (to jest to, co robię teraz), ale nie sądzę, że jest to dobre, ponieważ kiedy chcę uzyskać dostęp lub usunąć dane z pamięci podręcznej, muszę najpierw uzyskać całą grupę. grupa ma jeden milion artykułów, w którym możesz sobie wyobrazić jaki rodzaj tablicy będę iterował i se arching

Czy masz lepsze pomysły na to, jak mogę osiągnąć efekt grupowy?


edit: znaleźć inne rozwiązanie, nie wiem, czy to o wiele lepiej, bo nie wiem na ile wiarygodne jest jeszcze. Dodaję specjalny klucz o nazwie __paths, który jest w zasadzie wielowymiarową tablicą zawierającą pełne prefiksowane ścieżki kluczy dla wszystkich innych wpisów w pamięci podręcznej. A kiedy żądam lub usuwam pamięć podręczną, używam tej tablicy jako odnośnika, aby szybko znaleźć klucz (lub grupę kluczy), które muszę usunąć, więc nie muszę przechowywać tablic i powtarzać przez wszystkie klucze ...

Odpowiedz

18

Na podstawie swoich obserwacji, spojrzałem na podstawowym zastosowaniem modelu C buforowania APC „s (apc_cache.c), aby zobaczyć, co udało mi się znaleźć.

Źródło potwierdza twoje obserwacje, że w magazynie danych baz danych nie istnieje struktura grupująca, tak że wszystkie luźno pogrupowane zbiory obiektów będą musiały zostać wykonane w oparciu o pewne ograniczenia przestrzeni nazw lub modyfikację samej warstwy pamięci podręcznej. Miałem nadzieję znaleźć backdoora polegającego na kluczowym łańcuchowaniu za pomocą połączonej listy, ale niestety wydaje się, że kolizje są uzgadniane przez bezpośrednią realokację zderzającego się gniazda zamiast chaining.

Dalsze zakłócanie tego problemu, wydaje się, że APC używa jawnego modelu pamięci podręcznej dla wpisów użytkowników, zapobiegając ich starzeniu. Tak więc the solution Emil Vikström provided, który opiera się na LRU modelu memcached, niestety nie zadziała.

bez modyfikowania kodu źródłowego samej APC, oto co zrobię:

  1. Zdefiniuj ograniczenia przestrzeni nazw, które wpisy spełnia wymogów. Jak pierwotnie zdefiniowałeś powyżej, będzie to coś w stylu article_ dodawanego do każdego z twoich wpisów.

  2. Definicja oddzielnej listy elementów w tym zestawie. W rzeczywistości byłby to schemat, który opisałeś powyżej, ale w tym przypadku możesz użyć jakiegoś typu liczbowego, aby uczynić to bardziej wydajnym niż przechowywanie dużej ilości wartości łańcuchowych.

  3. Definiowanie interfejs aktualizacją tego zestawu wskaźników i pogodzenia ich z pamięci podręcznej podkład, w tym (co najmniej) metody insert, delete i clear. Po wywołaniu clear przejdź każdy ze swoich wskaźników, zrekonstruuj klucz użyty w składnicy danych zaplecza i opróżnij każdy z pamięci podręcznej.

Co mam promując tutaj jest dobrze zdefiniowany przedmiot, który wykonuje operacje szukacie sprawnie. Jest to skalowalne liniowo z liczbą wpisów w twojej pod-pamięci podręcznej, ale ponieważ używasz typu liczbowego dla każdego elementu, potrzebujesz ponad 100 milionów wpisów, zanim zaczniesz doświadczać prawdziwego bólu pamięci przy ograniczeniu, na przykład kilkaset megabajtów.


Tamas Imrei pokazał mi suggesting an alternate strategy byłem już w procesie dokumentowania, ale ma kilka poważnych wad Chciałbym omówić.

Jak określono w podłożu kodu C APCIterator jest liniowy Czas działania na całej zestaw danych podczas wyszukiwania (za pomocą jego konstruktora public __construct (string $cache [, mixed $search = null ...]])).

Jest to zdecydowanie niepożądane w przypadku, gdy poszukiwane elementy stanowią mały procent wszystkich danych, ponieważ każdy element w pamięci podręcznej byłby w stanie znaleźć te, których pragniesz. Powołując apc_cache.c:

/* {{{ apc_cache_user_find */ 
apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, \ 
    int keylen, time_t t TSRMLS_DC) 
{ 
    slot_t** slot; 
    ... 
    slot = &cache->slots[h % cache->num_slots]; 
    while (*slot) { 
     ... 
     slot = &(*slot)->next; 
    } 
} 

Dlatego chciałbym najsilniej zalecamy użycie wydajnego, wskaźnik oparty na wirtualnym grupowania rozwiązanie problemu jak już zarysowane powyżej.Chociaż w przypadku, gdy jesteś poważnie ograniczony pamięcią, podejście iteracyjne może być najbardziej poprawne, aby zaoszczędzić jak najwięcej pamięci kosztem obliczeń.

Powodzenia z aplikacją.

+1

Dobra robota! Gorąco polecam przeczytanie tego posta. –

+1

@ EmilVikström Dziekujemy! Cieszę się, że moja praca była wnikliwa. – MrGomez

4

miałem ten problem raz z memcached i rozwiązać go za pomocą numeru wersji w moich kluczy, tak:

version -> 5 
article_5_5 -> cached data 
article_10_5 -> cached data 
article_17_5 -> cached data 

Wystarczy zmienić numer wersji i grupa będzie skutecznie „gone”!

Aplikacja memcached używa najmniej ostatnio używanych zasad do usuwania starych danych, aby grupa w starej wersji została usunięta z pamięci podręcznej, gdy jest potrzebna. Nie wiem, czy APC ma tę samą funkcję:.


Według MrGomez to nie działa dla APC. Przeczytaj jego wpis i miej na uwadze mój post tylko dla innych systemów pamięci podręcznej, które korzystają z najmniej ostatnio używanych zasad (nie APC).

+0

APC nie ma zasad LRU, ale apc_add zezwala na TTL, Time To Live. Memcache byłby lepszym wyborem w tym przypadku dla tego rodzaju danych, ze względu na jego LRU. –

3

Można użyć APCIterator class co wydaje się szczególnie do wykonywania zadań istnieje jak ten:

klasa

APCIterator ułatwia iteracyjnego duże bufory APC. Jest to przydatne, gdyż pozwala Iterowanie nad dużymi skrytek w krokach ...

1

Niestety, APC nie może tego zrobić. Żałowałem sobie wystarczająco często, że to możliwe. Więc szukałem alternatyw.

Zend_Cache ma interesujący sposób robienia tego, ale po prostu używa pamięci podręcznych do buforowania informacji o tagach. Jest to składnik, który z kolei może używać backendów (takich jak apc). Jeśli chcesz pójść o krok dalej, możesz zainstalować Redis. Ten ma wszystko to natywnie zawarte i kilka innych naprawdę interesujących funkcji. To prawdopodobnie najczystsze rozwiązanie. Jeśli byłeś w stanie używać APC, powinieneś być również w stanie używać Redis.

Powiązane problemy