Memcached kullanımı: veritabanını güncellerken önbelleği güncellemek iyi bir uygulama mudur?


13

Bu soru mimarideki en iyi uygulamalar hakkındadır.

Mevcut Mimarimiz

Kullanıcı bilgisi için MySQL erişen bir PHP sınıfı var. Haydi diyelim User. Userbirçok kez erişildiğinden, yükü azaltmak için önbellek katmanları uyguladık.

İlk katman, "istek başına" önbellek dediğimiz şeydir. Veriler MySQL'den alındıktan sonra, verileri özel bir özelliğinde saklarız User. Veriler için daha sonra yapılan istekler, MySQL'den verileri yeniden istemek yerine özelliği döndürür.

Web isteği isteğe bağlı olarak yaşadığından ve öldüğünden, bu önbellek uygulamanın MySQL'e tek bir istekte yalnızca bir kereden fazla erişmesini önler.

İkinci katmanımız Memcached. Özel mülk boş olduğunda, önce veriler için Memcached'i kontrol ederiz. Memcached boşsa veriler için MySQL'i sorgularız, Memcached'i günceller ve User.

Soru

Uygulamamız bir oyundur ve bazen bazı verilerin olabildiğince güncel olması zorunludur. Yaklaşık beş dakika içinde, kullanıcı verileri için bir okuma talebi 10 veya 11 kez olabilir; bir güncelleme olabilir. Sonraki okuma isteklerinin güncel olması veya oyun mekaniği başarısız olması gerekir.

Yani, yaptığımız şey bir veritabanı güncellemesi gerçekleştiğinde yürütülen bir kod parçasını uygulamak. Bu kod, güncellenmiş verilerle Memcached'da anahtarı ayarlar, böylece Memcached'a gelen tüm istekler günceldir.

Bu uygun mu? Bunun gibi bir "yaşayan önbellek" tutmaya çalışırken dikkat etmemiz gereken herhangi bir performans kaygısı veya başka "gotchas" var mı?


Bunun verilerin silinmesi ve yeniden eklenmesi ile ne ilgisi var?
Mike Nakis

Soru başlığı açıklığa kavuşturuldu.
Stephen

Neden yalnızca önbelleğe alınan verilerin süresi dolmuyor? Güncelleme, güncellemenin korunmasını sağlamanız gerektiği anlamına gelir (böylece yeni verilerin bu şekilde güncellenmesi gerekiyorsa, güncellemeyi değiştirmeye devam etmeniz gerekir). Önbelleğin süresinin dolması, her şeyin veritabanından yeni alındığı anlamına gelir --- ve yeni güncellemelerin güncelleme kodunda yeni değişikliklere ihtiyacı yoktur. Dezavantajı, veritabanı yükünün daha yüksek olabilmesidir.
Peter K.

@Peter Evet, bunu da düşündük. Mevcut yaklaşımımızla ilgili başka bir sorun ortaya çıkmazsa, buna bağlı kalacağız. Aksi takdirde tarif ettiğinizle gidebiliriz.
Stephen

1
@Stephen Tanımladığınız yaklaşıma "Önbellekle Yaz" denir ve oldukça yaygın bir yaklaşımdır.
Sripathi Krishnan

Yanıtlar:


10

Benim önerim kullanım profilinize ve önbellek gereksinimlerinize bakmak.

Eski verileri memcached'de bırakmanız için hiçbir neden göremiyorum. Sanırım doğru yaklaşımı seçtiniz: DB'yi güncelleyin.

Her durumda, DB güncellemenizde (yaptığınız) bir sarıcıya ihtiyacınız olacak. Kullanıcıyı DB'de ve RAM'de güncellemek için kodunuz da memcached'e bir itme veya OR içinde memcached'de bir sonlandırma yapmalıdır.

Örneğin - Kullanıcılarınız oturumu kapatma işleminin bir parçası olarak normalde oturum başına bir kez güncelleme yaparsa, önbellekteki verileri güncellemenin fazla bir anlamı yoktur (örneğin toplamda yüksek puan) - hemen süresinin dolması gerekir.

Bununla birlikte, verileri güncelleyeceklerse (örneğin, mevcut oyun durumu) ve daha sonra 0,2 saniye sonra, verileri isteyecek hemen bir PHP sayfası isabeti alırsanız, önbellekte taze olmasını istersiniz.


3

Ana hatlarıyla anlattığınız gibi devam etmem. Yapmanız gereken şey, tamamen güncel verilere gerçekten ihtiyacınız olup olmadığına karar vermektir. Daha sonra, ihtiyacınız varsa, verilerin hangi bölümlerinin her zaman güncel olması gerektiğine karar verin ve bunları mimarinizde önbelleğe alınabilecek şeylerden ayırın.

Örneğin, muhtemelen kullanıcının e-posta adresini değiştirir değiştirmez güncellemek istersiniz, bu nedenle postaları yanlış adrese göndermezsiniz, ancak kullanıcının doğum tarihinin veya soyadının tamamen olması gerekmeyebilir. iyi bir kullanıcı deneyimi sağlamak için güncel. (NB Ne tür bir oyunu hedefleyeceğimi bilmediğim için bir oyun-mimari örneği kullanmıyorum ve bence bunun anlaşılması oldukça kolay).

Bu şekilde iki net veri kümeniz olur: kısa ve uzun vadeli önbelleğe alınabilir veriler. Büyük olasılıkla DB üzerindeki yükü hafifletmek için kısa vadeli verilerde bir dakikalık önbellek süresi ile kurtulabilirsiniz, ancak uzun vadeli veriler önbellekte kayma süresinde olduğu sürece kalabilir Kullanılmış.

O zaman güncellemelerle uğraşmanız gerekir. Öncelikle öğeleri bir kez güncelliğini yitirmiş olduklarında önbellekten kaldırmak için bir DB tetikleyici kullanmaya bakıyordum. Bu, iş katmanınızı, bir sonraki veri isteğinde önbellek yenilemesini tetiklemeye zorlar, veriler kullanılmazsa önbellekte biraz yer açar (örneğin, bir kullanıcı e-posta adresini değiştirirse hemen oturumu kapatır) . Bu, kullanıcı arayüzünde performans sorunlarına neden olacaksa (yani, önbellek yenilemelerini beklerken çok fazla gecikme getirin), öğe önbellekten kaldırıldıktan sonra yalnızca önbellek çağrısını tetiklemeye bakabilirsiniz. Ayrıca, önbelleği yenilemede indüklenen gecikmelerin minimum olmasını sağlamak için bu küçük veri kümesi için DB okuma sürelerini optimize etmeye bakarım (sadece gerçekten ihtiyacınız olan verileri yüklemeniz gerektiğinden bu daha kolay olmalıdır).

Ne yapmazdım, her durumda, önbelleği doldurmak için ek bir yöntem eklemek, o zaman iki yerde ((ve API kanca vb) çağrı korumak gerekir.

Gotchas gelince, doğrudan önbelleğe yazıyorsanız dikkatli olmanız gereken ana şey senkronizasyondur. Sessiz güncellemenizi yaparken birçok iş parçacığı okumaya çalışırsa, bazılarında geçersiz veri sorunları olabilir, bu da verileri ilk etapta güncel tutmaya çalışmayı engelleyecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.