Primary veritabanının CPU’su sürekli tavandaydı. İlginç olan şuydu: yazma oranı düşüktü. Yükün neredeyse tamamı okumaydı — rapor sayfaları, listeleme endpoint’leri, arama. Tek bir primary, kendisine hiç ihtiyaç duymayan bir sürü okumayı taşımaya çalışıyordu.
Okuma ve yazma yükünü ayırmak — read/write splitting — bu tablonun bilinen çözümü. Ama doğru zamanda ve doğru tuzakların farkında uygulanmazsa, çözdüğünden çok problem getirir.
Çoğu yük okuma ağırlıklıdır
Trafiğin ne kadarının okuma olduğu iş yüküne bağlıdır: standart OLTP benchmark’larının ölçümünde TPC-E %90,69 okumadır, TPC-C ise %65,71’de kalır — yani kendi oranınızı varsaymak yerine ölçün. Her sipariş bir kez yazılır, ama onlarca kez okunur: listede, detayda, raporda, panelde. Bu asimetri, read/write splitting’i cazip kılan şeydir — çünkü ölçeklemeniz gereken taraf bellidir.
Önce: bu gerçekten bir kapasite sorunu mu?
Replica eklemeden önce durun. Primary’nin dolu olması her zaman “kapasite bitti” demek değildir. Çoğu zaman tek bir eksik indeks, primary’yi olduğundan kat kat meşgul gösterir.
Bir replica eklemek — yeni bir sunucu, replication kurulumu, lag izleme — aslında bir CREATE INDEX’in çözeceği bir problemi pahalıya satın almak olabilir. Veri yoğunluklu sistemlerin kırılma noktaları yazısındaki sıra nettir: önce indeks disiplini, sonra replica. Bu sırayı atlamayın.
Sorgularınızı EXPLAIN ANALYZE ile ölçün. Primary, doğru indekslenmiş sorgular altında gerçekten doyuyorsa — işte o zaman replica.
Replica okumayı ölçekler, yazmayı değil
Net olalım: bir read replica, yazma kapasitenize hiçbir şey katmaz. Aynı yazmalar her replica’da yeniden oynanır. Replica okuma yükü problemini çözer; yazma yükü probleminiz varsa replica yanlış araçtır.
Laravel’de kurulum
Laravel, okuma/yazma bağlantı ayrımını doğal destekler:
// config/database.php
'pgsql' => [
'driver' => 'pgsql',
'read' => ['host' => ['10.0.0.2']], // replica
'write' => ['host' => ['10.0.0.1']], // primary
'sticky' => true,
// ...ortak ayarlar
],
SELECT’ler replica’ya, INSERT/UPDATE/DELETE’ler primary’ye gider. Replica’nın kendi bağlantı havuzu olur — primary’ninkinden ayrı; pgBouncer kullanıyorsanız ikisi ayrı havuzdur.
Replication lag: asıl fatura
Replica, primary’nin birkaç milisaniye — yük altında birkaç saniye — gerisindedir. Bu gecikme, read/write splitting’in gerçek bedelidir ve adı read-after-write problemidir.
sticky => true bunu kısmen çözer: bir istek içinde yazma yaptıysanız, aynı istekteki sonraki okumalar primary’ye gider. Ama sticky yalnızca tek bir istek sınırında çalışır.
Sınırın dışı hâlâ açıktır: kullanıcı profilini günceller (istek 1, primary’ye yazıldı), sonraki sayfaya geçer (istek 2, replica’dan okur) ve henüz replica’da oynanmamış eski profilini görür. Kullanıcı kendi yazdığı veriyi bayat görür. Bu bir bug gibi görünür ama aslında mimarinin kabul ettiği bir ödündür — bilerek kabul edilmesi gereken bir ödün.
Sorgu sınıflandırma disiplini
Read/write splitting’i kurmak, her okumanın şu soruya cevap vermesini gerektirir: bu sorgu bayat veri okuyabilir mi?
- Replica’dan okunabilir: listeler, raporlar, arama sonuçları, paneller. Birkaç saniye gecikme önemsiz.
- Primary’den okunmalı: hesap bakiyesi, stok adedi, yetki kontrolü, bir yazma kararının dayandığı her okuma.
Bu sınıflandırma artık mimarinin bir parçasıdır ve dokümante edilmesi gerekir. Yeni gelen bir geliştiricinin “bu sorgu nereden okumalı” sorusuna bakacak bir yeri olmalı — yoksa sınıflandırma sessizce çürür.
Ne zaman gerçekten gerekir
Read/write splitting şu üç koşul birlikte sağlandığında doğru hamledir:
- İndeks disiplini tamamlanmış; sorgular doğru indeksli ve hâlâ primary doyuyor.
- Yük ölçülmüş biçimde okuma ağırlıklı.
- Bayat-okuma sınıflandırmasını yapıp dokümante edecek disiplin var.
Bunlardan biri eksikse, replica’yı ertelemek daha ucuzdur.
Read/write splitting, dikey büyümeden ucuz bir ölçek hamlesidir — ama bedava değildir. Bedeli replication lag’dir ve onu görmezden gelmek, kullanıcıya kendi verisini eski göstermekle ödenir.
Okumayı ayırmadan önce, hangi okumanın bayatlığa dayanabileceğini bilin.

Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.