Cache Stampede Problemi
<p>Yüksek trafik uygulamaları geliştirirken, ağır veritabanı yanıtlarını önbellekleme, ilk savunma hattınızdır. Örneğin, veritabanından derlenmesi 4 saniye süren dev bir kurumsal analitik kontrol paneliniz olduğunu düşünün. Bu yük verisini 24 saat boyunca önbelleğe alıyorsunuz: <code>Cache::remember('analytics_data', 86400, ...)</code>. Bu yapılandırma, trafikle mükemmel bir şekilde başa çıkıyor - ta ki önbellek süresi dolana kadar.</p>
<p>24 saatlik pencerenin kapanma anında, önbellek anahtarı null hale gelir. Eğer 500 eşzamanlı kullanıcı tam o anda o kontrol paneli yoluna erişirse, tüm 500 isteği aynı anda bir önbellek hatası ile karşılaşacaktır. Ön bellek boş olduğu için, tüm 500 istek aynı anda 4 saniyelik ağır veritabanı derleme sorgusunu çalıştırır. Veritabanı CPU’su %100’e çıkar, bağlantı havuzları tükenir, yanıt süreleri düşer ve uygulamanız aniden kapanır. Bu başarısızlık durumu Cache Stampede (ya da Thundering Herd problemi) olarak bilinir. Yüksek trafik düşüşlerine karşı dayanabilmek için Atomic Cache Locks zorunludur.</p>
<h2>Çözüm: Mutex ile Kilitlenmiş Yeniden Üretim</h2>
<p>Atomic cache lock, bir önbellek anahtarı süresi dolduğunda yalnızca *bir tek sunucu işlemi* veritabanıyla konuşma izni alarak önbellek değerini yeniden inşa etmesine izin verir. Diğer tüm gelen talepler, sabırlı bir şekilde bekletilir veya kısa bir süre için hafif bir eski görüntüyü kabul eder, böylece veritabanının çökmek yerine korunmasını sağlar.</p>
<h3>Laravel'de Atomic Cache Locks Uygulaması</h3>
<p>Laravel, çoklu sunucu ortamlarında dağıtılmış atomic kilitleri yönetmek için Redis önbellek sürücüsünü kullanarak şık bir yürütme sarıcısı sunar.</p>
<pre><code>namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class DashboardMetricsController extends Controller
{
public function getEnterpriseMetrics()
{
$cacheKey = ‘enterprise_metrics_payload’;
$lockKey = ‘metrics_regeneration_lock’;
// 1. Hızlı önbellek yolundan verileri doğrudan almaya çalış
$data = Cache::get($cacheKey);
if ($data) {
return response()->json($data);
}
// 2. ÖNBELLEK HATASI: Veritabanına erişmeden önce Redis kullanarak atomic lock alın
// Veritabanı hesaplamasının tamamlanması için 10 saniye boyunca kilit alıyoruz
$lock = Cache::lock($lockKey, 10);
if ($lock->get()) {
try {
\Log::info("Kilit alındı. Temel veritabanı tablolarından metrikler yeniden üretiliyor.");
// 3. Ağır, yoğun veritabanı toplama sorgusunu güvenli bir şekilde çalıştır
$data = DB::table('orders')
->selectRaw('SUM(total) as revenue, COUNT(id) as volume, status')
->groupBy('status')
->get()
->toArray();
// 4. Sonraki talepler için önbelleği hemen doldur
Cache::put($cacheKey, $data, now()->addDay());
return response()->json($data);
} finally {
// İşlem sona erdiğinde atomic lock her zaman serbest bırakılmalıdır!
$lock->release();
}
}
// 5. GÜVENLİK ÖNLEMİ: Eğer başka bir işçi süreci zaten kilidi kapattıysa,
// veritabanını çiğnemek yerine kısa bir süre uyuyarak yeniden önbelleğe alınan veriyi çekmeye çalışın.
sleep(1);
return response()->json(Cache::get($cacheKey) ?? ['status' => 'processing_retry']);
}}
<h2>Mühendislik ROI’si</h2>
<p>Ağır analitik sorgularında atomic cache kilidi uygulayarak yüksek tahmin edilebilir bir veri katmanı oluşturursunuz. Yüksek frekanslı sona erme süreleri artık ani donanım arızaları yaratamaz. Veritabanınız düzgün bir yük ile başa çıkarken, dağıtılmış Redis düğümleriniz eşzamanlı trafik hacmini rahatlıkla karşılayabilir.</p>Kaynak: Orijinal Makale


