Redis’in izin kontrolü için ne kadar daha hızlı olduğu sıkça sorduğum bir sorudur. Cevap, ölçeğinize, erişim desenlerinize ve neyi ölçtüğünüze bağlıdır.
<p>Gerçek sayılar elde etmek için bir <a href="https://github.com/scabarcas17/laravel-permissions-redis-benchmark" target="_blank" rel="noopener noreferrer">benchmark uygulaması</a> geliştirdim. İşte bulgularım.</p>
<h2>
<a name="methodology" href="#methodology"></a>
Metodoloji
</h2>
<h3>
<a name="the-setup" href="#the-setup"></a>
Kurulum
</h3>
<ul>
<li>
<strong>PHP 8.3</strong> OPcache etkin
</li>
<li>
<strong>Laravel 12</strong> varsayılan yapılandırma ile
</li>
<li>
<strong>Redis 7.2</strong> yerel (aynı makine, minimal ağ gecikmesi) çalışıyor
</li>
<li>
<strong>MySQL 8.0</strong> yerel olarak çalışıyor
</li>
<li>
<strong>Karşılaştırılan paketler:</strong>
<ul>
<li>
<code>spatie/laravel-permission</code> v6 (veritabanı destekli, Redis'i Laravel önbellek sürücüsü olarak kullanıyor)
</li>
<li>
<code>scabarcas/laravel-permissions-redis</code> v3 (Redis SET'leri, çift katmanlı önbellek)
</li>
</ul>
</li>
</ul>
<h3>
<a name="the-data" href="#the-data"></a>
Veriler
</h3>
<ul>
<li>1 kullanıcıya 3 rol üzerinden 50 yetki atanmıştır</li>
<li>Yetkiler şu gruplarda yapılandırılmıştır: <code>posts.*</code>, <code>users.*</code>, <code>settings.*</code>, <code>reports.*</code></li>
<li>Her iki paket de önerilen varsayılan ayarlarıyla yapılandırılmıştır.</li>
</ul>
<h3>
<a name="what-we-measure" href="#what-we-measure"></a>
Ne Ölçüyoruz
</h3>
<ol>
<li>
<strong>Veritabanı sorguları</strong> — Her istek başına MySQL'e giden sorgu sayısı
</li>
<li>
<strong>Önbellek mimarisi</strong> — Her paketin izin verilerini nasıl depoladığı ve geri aldığı
</li>
<li>
<strong>Geçersiz kılma maliyeti</strong> — İzinler değiştiğinde ne olur
</li>
<li>
<strong>Soğuk başlangıç</strong> — Önbellek temizlendikten sonraki ilk istek
</li>
<li>
<strong>Isınmış durum</strong> — Sabit durum performansı
</li>
</ol>
<blockquote>
<p><strong>Adil karşılaştırma için önemli not:</strong> Spatie, en hızlı önbellek arka ucunu sağlamak için <code>CACHE_DRIVER=redis</code> ile yapılandırılmıştır. Bu karşılaştırma, mimarideki farkla ilgilidir, "veritabanı vs Redis" anlamında değil.</p>
</blockquote>
<h2>
<a name="benchmark-1-database-queries-per-request" href="#benchmark-1-database-queries-per-request"></a>
Benchmark 1: İstek başına veritabanı sorguları
</h2>
<p>Test uygulamamızda tipik bir istek 33 izin kontrolü (middleware + politika + çevrimiçi kontroller) gerçekleştirir. Her paketin oluşturduğu veritabanı sorgusu sayısı şu şekildedir:</p>
<div class="table-wrapper-paragraph">
<table>
<thead>
<tr>
<th>Senaryo</th>
<th>spatie/laravel-permission</th>
<th>laravel-permissions-redis</th>
<th>Azalma</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>1 istek (soğuk önbellek)</strong></td>
<td>5 sorgu</td>
<td>1 sorgu</td>
<td><strong>80%</strong></td>
</tr>
<tr>
<td><strong>1 istek (ısınmış önbellek)</strong></td>
<td>0 sorgu</td>
<td>0 sorgu</td>
<td>--</td>
</tr>
<tr>
<td><strong>10 ardışık istek</strong></td>
<td>14 sorgu</td>
<td>10 sorgu</td>
<td><strong>~29%</strong></td>
</tr>
<tr>
<td><strong>50 ardışık istek</strong></td>
<td>54 sorgu</td>
<td>50 sorgu</td>
<td><strong>~7%</strong></td>
</tr>
</tbody>
</table>
</div>
<h3>
<a name="why-the-numbers-converge" href="#why-the-numbers-converge"></a>
Neden sayılar birbirine yaklaşır
</h3>
<p>Her iki paket de ilk istekten sonra önbellekler. Ardışık isteklere gelen farklılık ise önbellek geçersiz kılma davranışından gelir, ki bunu bir sonraki bölümde değineceğiz.</p>
<p>Asıl hikaye, önbellek ısınmadığında neler olduğunda yatıyor.</p>
<h2>
<a name="benchmark-2-cache-architecture-deep-dive" href="#benchmark-2-cache-architecture-deep-dive"></a>
Benchmark 2: Önbellek mimarisi derinlemesine inceleme
</h2>
<p>Mimari farklılıkların en fazla önem kazandığı yer burasıdır.</p>
<h3>
<a name="how-spatie-stores-permissions" href="#how-spatie-stores-permissions"></a>
Spatie izinleri nasıl depolar?
</h3>
<div class="highlight js-code-highlight">
<pre class="highlight plaintext"><code>Cache key: "spatie.permission.cache"Value: Tüm kullanıcılar için TÜM izinlerin serileştirilmiş PHP dizisi
<p>Her <code>hasPermissionTo()</code> çağrısında:</p>
<ol>
<li>Redis'den tam serileştirilmiş blob'u al</li>
<li>Serileştirmeyi çöz (<code>unserialize()</code>)</li>
<li>Geçerli kullanıcı için izinleri filtrele</li>
<li>İstenilen izin için sonuç dizi taraması yap</li>
</ol>
<p><strong>Kontrol başına zaman karmaşıklığı:</strong> O(n) burada n = sistemdeki toplam izin sayısı</p>
<h3>
<a name="how-laravelpermissionsredis-stores-permissions" href="#how-laravelpermissionsredis-stores-permissions"></a>
laravel-permissions-redis izinleri nasıl depolar?
</h3>
<div class="highlight js-code-highlight">
<pre class="highlight json"><code>Redis key: "auth:user:42:permissions"Value: Redis SET { “posts.create”, “posts.edit”, “users.view”, … }


