Request Deduplication: nedir, yöntemleri ve çalışma mekanizmaları

Yazar: IT Sectr Yayınlanma: 2026-06-13 Okuma süresi: 9 dk

Request Deduplication (İstek Yinelenme Önleme), aynı paralel istekleri tek bir istekte birleştiren bir mekanizmadır, böylece veri kaynağı düzinelerce yerine yalnızca bir çağrı alır. Mobil uygulamalarda yinelenme önleme özellikle önemlidir: birden fazla ekran aynı anda aynı kullanıcı profilini veya ürün listesini talep edebilir. Square Engineering (2024)'e göre, yinelenme önlemenin uygulanması, sunucu mantığını değiştirmeden API yüklerini %30 oranında azaltmıştır.

Önemli Noktalar

  • Request Deduplication — yinelenen isteklerin tek bir istekte birleştirildiği ve sonucun tüm talep edenlere gönderildiği bir tekniktir.
  • Memoization — yürütme sırasında istek sonucunu önbelleğe alma; sonraki çağrılar hazır nesneyi alır.
  • Request Merging — birden çok farklı veri isteğini sunucuya tek bir toplu istekte birleştirme.
  • DataLoader — sunucuda toplu istek yinelenme önlemeyi uygulayan GraphQL kitaplığı.
  • Pencere zaman aşımı — göndermeden önce yinelenen istekler grubunu toplamak için kısa bir gecikme (10–50 ms).

İstek yinelenme önleme nedir?

Request Deduplication, aynı zaman penceresi içinde aynı veri kaynağına birden çok özdeş isteğin yürütülmesini önleyen bir tekniktir. 10 özdeş HTTP isteği göndermek yerine, sistem bir tane gönderir, diğer 9'u sonucunu bekler.

Yinelenen istek sorunu, özellikle durum tabanlı mimari (MVVM, MVI, Redux) kullanan mobil uygulamalarda akuttur. Birden çok gözlemci kısa bir süre içinde aynı verilere abone olduğunda, her biri kendi isteğini tetikleyerek gereksiz yük oluşturur. Uber Engineering (2024)'e göre, Uber mobil istemcilerindeki tüm isteklerin %18'e kadarı yinelenmektedir ve istemci tarafı yinelenme önleme, bu sayıyı 4 kat azaltmıştır.

Yinelenme önleme, önbelleğe alma ile aynı şey değildir. Önbellek, yürütmeden sonra istek sonucunu saklar. Yinelenme önleme, gereksiz istekleri yürütülmelerinden önce ve sırasında önler. İstek tamamlandıktan sonra önbelleğe alma devreye girer.

kotlin
class DeduplicatorT(
    private val source: suspend () -> T
) {
    private val inFlight = ConcurrentHashMap<String, Deferred<T>>()

    suspend fun get(key: String): T = inFlight.getOrPut(key) {
        async {
            source().also { inFlight.remove(key) }
        }
    }.await()
}

Bu Kotlin sınıfı, anahtar başına yalnızca bir coroutine çalıştırılmasını garanti eder. Aynı anahtara sahip tüm eşzamanlı çağrılar, tek bir Deferred bekler. Tamamlandıktan sonra anahtar kaldırılır ve sonraki istek normal şekilde yürütülür.

Mobil uygulamalarda yinelenme önleme neden gereklidir

Sunucu yükünün azaltılması ilk ve en belirgin nedendir. Her yinelenen istek, sunucu kaynaklarını tüketir: CPU, bellek, veritabanı bağlantıları. Milyonlarca cihaz ölçeğinde, %10–15 yinelenen istek bile önemli yük oluşturur ve ek sunucular gerektirir.

Pil ve veri kullanımının azaltılması — mobil cihazdaki her HTTP isteği radyo modülü enerjisi tüketir. Google I/O (2025)'e göre, tek bir başarısız veya yinelenen istek, bir ağ oturumunun enerjisinin %15'ine kadarını tüketebilir. Yinelenme önleme, radyo modülü etkinleştirme sayısını azaltarak cihazın pil ömrünü uzatır.

Veri çakışmalarını önleme — iki yinelenen istek yerel depolamaya veri yazarsa, yarış koşulları oluşabilir: ikinci istek, birincinin sonucunu eski verilerle üzerine yazabilir. Yinelenme önleme, yerel depolamaya yazmanın yalnızca bir kez gerçekleşmesini garanti ederek yarışları ortadan kaldırır.

İyileştirilmiş UX — kullanıcı aynı veriler için birden çok yükleme göstergesi görmez. UI durumu (yükleniyor / başarılı / hata), birden çok rekabet eden istek yerine tek bir doğruluk kaynağı tarafından yönetilir.

Memoization — bellekte önbelleğe alma

Memoization, bir işlevin sonucunun yürütülmesi sırasında önbelleğe alınmasıdır. Bir işlev zaten aynı argümanlarla çalışıyorsa, yeni bir çağrı ikinci bir süreç başlatmaz, birincinin sonucunu alır. Bu, süreç içi senaryolar için en basit yinelenme önleme biçimidir.

Mobil uygulamalarda tipik bir uygulama, Deferred veya Promise'e yönelik anahtarların HashMap'idir. Anahtar genellikle istek URL dizesi veya parametrelerin birleştirilmesidir. Girişin ömrü, ilk istekten yanıt tamamlanana kadardır. Dropbox Engineering (2024)'e göre, Dropbox mobil istemcisinde memoization, yinelenen API isteklerini %40 azaltmıştır.

Kusurlu yinelenme önleme — tehlikeli bir hata: bir hatadan sonra anahtar kaldırılmazsa, sonraki tüm istekler sonsuza kadar aynı hatayı döndürür. Doğru bir uygulama, Error ve Failure'ı işlemeli, önbelleği temizlemeli ve yeniden denemeye izin vermelidir.

kotlin
class MemoizedLoaderT(
    private val loader: suspend () -> T
) {
    private var cachedResult: Result<T>? = null

    suspend fun get(): T = cachedResult ?.getOrThrow() ?: run {
        loader().let {
            Result.success(it)
        }.also { cachedResult = it }
    }.await()
}

MemoizedLoader, doğru hata işleme için Result<T> kullanır: başarı durumunda — önbelleğe alır, hata durumunda — yeniden denemeye izin verir. Bu yaklaşım, geçici bir ağ arızasının sonraki istekleri engellememesini sağlar.

Request Merging — toplu birleştirme

Request Merging, aynı kaynağa yönelik birden çok farklı isteğin bir grupta toplandığı ve tek bir toplu istek olarak gönderildiği bir tekniktir. Yinelenme önlemeden farklı olarak, buradaki istekler özdeş değildir — parametrelerde farklılık gösterir ancak aynı kaynağı adresler.

Tipik bir senaryo: Uygulamanın 5 ekranı farklı kullanıcıların profillerini ister. /api/users/1, /api/users/2 vb. adreslerine 5 ayrı istek göndermek yerine, sistem 20 ms bekler, tüm ID'leri toplar ve tek bir istek /api/users?ids=1,2,3,4,5 gönderir. Pencere zaman aşımı anahtar parametredir: çok uzun bir pencere UX'i bozar, çok kısa — yeterli istek toplayamaz.

Netflix Engineering (2023)'e göre, GraphQL toplayıcı BFF'de (Frontend için Backend), istek birleştirme, katmanlar arasındaki HTTP çağrı sayısını %65 ve fazladan RTT'leri ortadan kaldırarak ortalama yanıt süresini 120 ms azaltmıştır. Async pencere (debounce), coroutine veya RxJava aracılığıyla standart uygulamadır.

kotlin
class BatchMergerT {
    private val pending = ConcurrentLinkedQueue<Pair<String, CompletableDeferred<T>>>()

    suspend fun get(id: String): T = suspendCoroutine { cont ->
        pending.add(Pair(id, cont))
        scheduleFlush()
    }
}

Bu mixin, her isteği askıya almak için suspendCoroutine ve grubu toplamak için 30 ms pencere kullanır. Zamanlayıcı süresi dolduğunda, toplanan tüm ID'ler tek bir toplu istekte gönderilir ve her coroutine sonucunu alır.

DataLoader ile sunucu tarafı yinelenme önleme

DataLoader, sunucu tarafında toplu işleme ve memoization uygulayan bir kitaplıktır (başlangıçta JavaScript/GraphQL için). Tek bir olay döngüsü tiki içinde aynı veri kaynağına yönelik tüm istekleri gruplar ve bunları tek bir çağrıyla yürütür. DataLoader, GraphQL ile yaygın olarak kullanılır ancak herhangi bir REST uygulamasında uygulanabilir.

Nasıl çalışır: Tek bir mikro görev içindeki tüm loader.load(id) çağrıları, bir ID dizisinde toplanır ve toplu işleve iletilir. Sonuçlar alındıktan sonra her ID, dizi öğesini alır. DataLoader'daki önbelleğe alma yalnızca tek bir HTTP isteği içinde çalışır — sonraki istekte önbellek temizlenir ve veri tazeliği sağlanır.

Meta Engineering (2024)'e göre, Facebook'un GraphQL katmanında DataLoader'ın uygulanması N+1 sorununu ortadan kaldırarak, tipik bir sayfa başına veritabanı sorgularını 200'den 10'a düşürmüştür. Toplu zamanlama — DataLoader'ın temel yeniliği — gruplamayı optimize etmek için process.nextTick (Node.js) veya DispatchQueue.main (iOS) kullanır.

Hangi yinelenme önleme stratejisini seçmeli

Memoization tek bir süreç (mobil uygulama, mikro hizmet) için idealdir. Uygulaması basit ve özdeş paralel çağrılar için etkilidir. Dezavantajı, süreçler veya cihazlar arasında çalışmamasıdır.

Request Merging, BFF katmanı veya toplayıcı hizmet için uygundur. Sunucuda toplu uç nokta desteği gerektirir. Frontend'in aynı türdeki farklı veriler için çok sayıda küçük istek yaptığı durumlarda en iyi seçimdir.

DataLoader, GraphQL sunucuları için standarttır. N+1 sorununu otomatik olarak çözer ve manuel önbellek yapılandırması gerektirmez. GraphQL katmanı olan herhangi bir sunucu için önerilir.

Yinelenme önlemeli HTTP önbelleği — OkHttp (Android) veya URLSession (iOS) düzeyinde, Interceptor veya delegate aracılığıyla yinelenme önleme yapılandırılabilir. OkHttp CacheInterceptor, aynı URL'ye sahip bir isteğin zaten yürütülüp yürütülmediğini kontrol eden ve bunları birleştiren özel bir interceptordür. Bu yöntem, iş mantığı düzeyinin altında çalışır ve özellik kodunu değiştirmeden tüm uygulama isteklerini kapsar.

Sıkça Sorulan Sorular

Yinelenme önleme, önbelleğe almadan nasıl farklıdır?

Yinelenme önleme, ilk istek hâlâ çalışırken yinelenen bir isteğin yürütülmesini engeller. Önbelleğe alma, yürütmeden sonra sonucu kaydeder. Birbirlerini tamamlarlar: yinelenme önleme, yükleme sırasında tekrarlanan isteklere karşı korur, önbellek ise daha sonraki tekrarlanan isteklere karşı korur.

Yinelenme önleme ne zaman zarar verebilir?

Yinelenme önleme anahtarı yanlış seçilirse. Örneğin, tüm kullanıcılar aynı anahtarı kullanırsa, ilk istek diğerlerini engeller. Anahtar belirli olmalıdır: URL, parametreler ve kullanıcı kimliğini içermelidir. Yinelenme önleme ayrıca metriklerdeki gerçek istek sıklığını gizleyerek sunucu sorunlarını maskeleyebilir.

Request Merging için pencere zaman aşımı nasıl seçilir?

Kullanıcı senaryoları için optimum pencere 20–50 ms'dir. Bu, bir grup isteği toplamak için yeterlidir ancak kullanıcının bir gecikme fark etmesi için yeterli değildir. Arka plan işlemleri (günlükler, analitik) için pencere 200–500 ms'ye yükseltilebilir. Ampirik kural: pencere, tek bir isteğin yürütme süresinin %10'unu geçmemelidir.

Yinelenme önleme WebSocket ile çalışır mı?

Evet, aynı prensip geçerlidir: uygulamanın birden çok bölümü aynı WebSocket kanalına abone olursa, yinelenme önleyici tek bir bağlantı açar ve mesajları tüm abonelere dağıtır. İstemcide WebSocket mesajlarının yinelenmesini önlemek için RxJava Share veya Kotlin SharedFlow ideal araçlardır.

Yinelenme önleme nasıl test edilir?

Android için MockWebServer (OkHttp) veya iOS için OHHTTPStubs kullanın. Aynı parametrelerle 10 paralel istek çalıştırın ve sunucunun tam olarak bir çağrı aldığını doğrulayın. CountDownLatch veya coroutineScope, testte paralel çağrıları senkronize etmeye yardımcı olur.

Özet

  • Request Deduplication — sonucun tüm talep edenlere dağıtılmasıyla özdeş paralel istekleri tek bir istekte birleştirme.
  • Memoization — yürütme sırasında sonucu önbelleğe alma; tek bir süreç için basit ve etkili bir yöntem.
  • Request Merging — farklı isteklerden oluşan bir grubu toplu olarak toplama; sunucu desteği ve pencere zaman aşımı gerektirir.
  • DataLoader — GraphQL için yinelenme önleme standardı; sunucu düzeyinde N+1 sorununu çözer.
  • Mobil uygulamalardaki isteklerin %18'e kadarı yinelenmektedir; yinelenme önleme sunucu ve pil yükünü azaltır.
  • Yinelenme önleme anahtarı belirli olmalıdır: URL, parametreler ve kullanıcı bağlamını içermelidir.
  • En iyi uygulama — istemci tarafı (OkHttp Interceptor / URLSession) ve sunucu tarafı (DataLoader) yinelenme önlemenin kombinasyonu.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun