, Paginated sonuçları önbelleğe güncelleme temizleniyor - çözmek için nasıl?

8 Cevap php

Ben bir forum oluşturduk, ve biz veritabanını bazı iş kurtarmak için apc ve memcache önbelleğe alma çözümü uygulayan ediyoruz.

Ben "Kategoriler :: GetAll" gibi tuşları ile önbellek katmanı uygulamaya başladı, ve ben kullanıcıya özgü verileri olsaydı, ben kullanıcı kimliği gibi şeylerle tuşları eklemek istiyorum, bu yüzden "User::getFavoriteThreads|1471" olsun istiyorum . Bir kullanıcı yeni bir favori konu eklendiğinde, ben önbellek anahtarını silmek istiyorum, ve bu girdiyi yeniden olacaktır.

However, and here comes the problem:

Ben bir forumda konuları önbelleğe istedi. Basit yeterli, "Forum :: getThreads | $ iForumId". Ama ... pagination ile, örneğin, çeşitli önbellek girdileri içine bu bölünmüş olurdu

"Forum::getThreads|$iForumId|$iLimit|$iOffset".

Birisi foruma yeni bir konu nakleder kadar, tamam hangisi. Ben şimdi ne olursa olsun sınır ve ofset, "Forum::getThreads|$iForumId" altındaki tüm anahtarlarını silmek zorunda olacak.

Ne bu sorunu çözmek için iyi bir yol olurdu? Hissetmesem gerçekten çok değil, her olası sınırı döngü ve ben artık uymuyor şey bulana kadar ofset.

Teşekkürler.

8 Cevap

Ayrıca önbellek sizi satın alacak ne kadar karşı çaba ve CPU maliyet açısından, önbellek veri depolama maliyeti bakmak isteyebilirsiniz.

Eğer forum manzaralı% 80 ipliklerinin ilk sayfasına bakarak olduğunu bulursanız, o zaman sadece o sayfayı önbelleğe karar verebilir. Yani hem önbellek okuma ve yazma implment çok basittir anlamına gelecektir.

Aynı şekilde, bir kullanıcının favori parçacığı listesi. Bu her kişi ziyaret nadiren sonra önbellek çok performansını artırmak olmayabilir bir şey varsa.

Just an update: I decided that Josh's point on data usage was a very good one. People are unlikely to keep viewing page 50 of a forum.

Bu modele dayanarak, ben her forumda 90 son konuları önbelleğe karar verdi. Getiriliyor işlevi Ben sınırını kontrol ve parçacığı belirtilen dilim önbellek içinde olup olmadığını görmek için ofset. Bu önbellek sınırı içinde ise, ben sağ kısmını almak ve geri dönmek için () array_slice kullanın.

Bu şekilde, ben forumda başına tek bir önbellek tuşunu kullanabilirsiniz, ve :-) / güncelleyin önbelleğini temizlemek için çok az çaba gerektirir

Ben de diğer daha kaynak ağır sorgularda, ben tuşları arasındaki ilişkileri saklamak, flungabunga modeli ile gitti işaret etmek istiyorum. Ne yazık ki yığın taşması beni iki cevapları kabul izin vermez.

Teşekkürler!

Aslında her zaman zor gidecek bir görünüm, önbelleğe çalışıyoruz. Veri nadiren değişir çünkü yerine, sadece önbellek verileri denemelisiniz. Iplik satırları önbelleğe, bir forum önbelleğe etmeyin. Sonra db çağrı sadece zaten önbellek var kimlikleri, listesini dönmelidir. Db çağrı herhangi bir MyISAM tablo üzerinde hızlı aydınlatma olacak ve daha sonra db bellek yiyor, büyük bir katılmak yapmak zorunda değilsiniz.

Evet bu bir turşu.

Ben anahtar değerleri için gruptan bir karma tablo içerecek bir korumalı özelliği olan özel bir sınıfın (diyelim ExtendedMemcache) ile memcache sınıfını genişleterek bu çözmek için başardınız.

The ExtendedMemcache->set method accepts 3 args ($strGroup, $strKey, $strValue) When you call set, it will store the relationship between $strGroup, and $strKey, in the protected property and then go on to store the $strKey to $strValue relationship in memcache.

Daha sonra bir dize geçirildiğinde, tuşları o gruba bağlı olduğunu göreceksiniz "DeleteGroup" denilen ExtendedMemcache sınıfına yeni bir yöntem eklemek ve sırayla her tuşa tasfiye olabilir.

It would be something like this: http://pastebin.com/f566e913b I hope all that makes sense and works out for you.

PS. Eğer statik aramaları korumalı özelliği o kendi anahtarının altında memcache kendisi kaydedilmiş olabilir kullanmak istedim sanırım. Sadece bir düşünce.

Flungabunga

Olası bir çözüm, bir forumda parçacığı önbelleği sayfalandırmak ziyade Forum::getThreads|$iForumId için iplik bilgi koymak değildir. Sonra PHP kodu sadece o verilen sayfa için istediğiniz olanları çekin, örneğin

$page = 2;
$threads_per_page = 25;
$start_thread = $page * $threads_per_page;

// Pull threads from cache (assuming $cache class for memcache interface..)
$threads = $cache->get("Forum::getThreads|$iForumId");

// Only take the ones we need
for($i=$start_thread; $i<=$start_thread+$threads_per_page; $i++)
{
    // Thread display logic here...
    showThread($threads[$i]);
}

Bu, her sayfada onları dışarı çekerek yapmak için biraz daha iş var, ama şimdi sadece yeni bir iş parçacığı güncelleme / ilave bir yerine önbelleği geçersiz endişelenmenize gerek yok demektir.

flungabunga: Your solution is very close to what I'm looking for. The only thing keeping me from doing this is having to store the relationships in memcache after each request and loading them back.

Ben bu demek ne kadar bir performans isabet emin değilim, ama bu biraz verimsiz gibi görünüyor. Ben bazı testler yapmak ve bunu nasıl eleştirdiğini göreceksiniz. (Ve bunu göstermek için bazı kod teşekkürler!) Yapısal bir öneriniz için teşekkür ederiz.

Karşı ölçmek zor gerçekleri kalmadan optimizasyon bu tür yaparken çok dikkatli olun.

Çoğu veritabanı zula çeşitli düzeylerde var. Bu doğru bir şekilde ayarlı ise, veritabanı muhtemelen kendi kendine yapabileceği daha önbelleğe alma çok daha iyi bir iş yapacak.

Flungabunga yanıt olarak:

Gruplandırma uygulamak için başka bir yol tuşları kendileri içine grup adını artı bir sıra numarası koymak ve "net" grubuna sıra sayısını artırmak için olduğunu. Sen kendi anahtarında her grup için geçerli geçerli sıra numarasını saklayın.

örneğin

get seqno_mygroup
23

get mygroup23_mykey
<mykeydata...>
get mygroup23_mykey2
<mykey2data...>

Sonra sadece grup "silmek" için:

incr seqno_mygroup

Voila:

get seqno_mygroup
24

get mygroup24_mykey
...empty

vb.