⚡ Caching & Messaging — Öğrenme & Mülakat Rehberi

Redis/Coherence ile cache stratejileri (TTL, eviction, pattern’ler) ve Kafka ile messaging temelleri, EOS (exactly-once), retry/DLT ve üretim ipuçları. Hem hızlı öğren hem de mülakata hazır ol.

🔎 Genel Bakış

  • Cache: Sıcak veriyi hızlı tut; doğru pattern ve TTL ile tutarlılık/performans dengesini kur.
  • Redis: Basit/çok hızlı; TTL, eviction, Lua, cluster, Pub/Sub.
  • Coherence: Oracle ekosisteminde ölçekli, distributed/near cache, entry processor.
  • Kafka: Dağıtık commit log; partition, acks, consumer group, offset ve EOS kritik.

🧱 Cache Temelleri

Cache Neden?

  • Okuma yoğun yüklerde latency ve DB baskısını azaltır.
  • Hot-key/Hot-set yaklaşımlarıyla maliyet ve performans dengesi.

Problem Alanları

  • Stale data (bayat veri), cache stampede, invalidation zorlukları.
  • Dağıtık tutarlılık, çoklu bölge (multi-DC) replikasyon.

🟥 Redis — Pratik Odaklı

Veri Tipleri & Kullanımlar

TipKullanımÖrnek
StringBasit cache (JSON), sayaçSET user:42 {...}
HashAlan bazlı kısmi güncelleHSET sess:abc user 42 ttl 3600
ListQueue, recent itemsLPUSH recent:log ...
SetBenzersiz toplulukSADD online:users 42
ZSetSıralı veri, leaderboardZADD rank 100 "neo"
Bitmap/HyperLogLogA/B, tahmini sayımPFADD uv:2024 user42

TTL & Eviction

  • EXPIRE key 60, PERSIST TTL’i kaldırır.
  • Eviction politikaları: volatile-lru, allkeys-lru, volatile-ttl, allkeys-random
PolitikaAçıklamaNe zaman?
allkeys-lruEn az kullanılanı atGlobal LRU, TTL olmasa da
volatile-ttlTTL’i en yakın olanı atHepsi TTL’li ise
allkeys-randomRastgele atBasit/öngörülebilir değil

Persistans & Yüksek Erişilebilirlik

  • RDB (snapshot) + AOF (append only). Karma kullanım önerilir.
  • Sentinel / Redis Cluster ile failover & sharding.

Stampede, Hot Key, Dağıtık Kilit

  • Stampede: dogpile için lock + double-checked cache ve jitter ekle.
  • Hot key: Replika/yerel cache, key’i böl (shard), replicated GET kullan.
  • Lock: Basit SET key val NX PX 5000; kritik işlerde Redlock varyantlarına dikkat.
# Basit kilit örneği
SET lock:product:42 1 NX PX 5000
# iş...
DEL lock:product:42
// Lettuce (Spring Data Redis ile)
var valueOps = redisTemplate.opsForValue();
String key = "user:42";
String cached = valueOps.get(key);
if (cached == null) {
  // DB'den oku
  String json = objectMapper.writeValueAsString(userService.get(42L));
  valueOps.set(key, json, Duration.ofMinutes(10)); // TTL
  cached = json;
}

🏛️ Oracle Coherence — Kısa Rehber

Önemli Kavramlar

  • Distributed / Near Cache: Uzak dağıtık veri; sık okunanlar için near cache.
  • Entry Processor: Sunucu tarafında atomik işleme (network trafiğini azaltır).
  • Continuous Query: Koşula uyan değişiklikleri izleme.

Pratik İpuçları

  • Çok okunan veriler için near cache + invalidation.
  • Coherence *Extend ile istemci–küme iletişimini yönetin.

🎯 Cache Desenleri & TTL/Eviction

Desenler

DesenÖzellikArtı/Eksi
Cache-AsideÖnce cache’e bak; yoksa DB, sonra cache’e yazBasit / Invalidation zor
Write-ThroughYazma yolunda cacheTutarlılık iyi / Yazma gecikmesi
Write-BehindÖnce cache, sonra async DBPerformans / Veri kaybı riski
Read-ThroughCache miss’te otomatik loadKod sade / Loader karmaşıklığı

TTL İpuçları

  • Veri tazeliğine göre TTL belirle; jitter (± rastgele) ekle.
  • Toplu invalidation için namespace versioning (örn. user:v7:42).

🌱 Spring Cache Entegrasyonu

Annotasyonlar

  • @Cacheable: Miss’te çağır, sonucu cache et.
  • @CachePut: Metot her çağrıldığında cache’i güncelle.
  • @CacheEvict: Invalidate.
@Cacheable(cacheNames="user", key="#id", unless="#result == null")
public UserView get(Long id){ return repo.findView(id); }

@CacheEvict(cacheNames="user", key="#id")
public void delete(Long id){ repo.deleteById(id); }
// Redis Cache Manager (TTL)
@Bean
RedisCacheManager redisCacheManager(RedisConnectionFactory cf) {
  var cfg = RedisCacheConfiguration.defaultCacheConfig()
      .entryTtl(Duration.ofMinutes(10))
      .disableCachingNullValues();
  return RedisCacheManager.builder(cf).cacheDefaults(cfg).build();
}

🦅 Kafka Temelleri

Çekirdek Kavramlar

  • TopicPartition’lara bölünür; ölçek ve paralellik.
  • Leader/Replica, ISR (in-sync replicas) → dayanıklılık.
  • Producer acks: 0 / 1 / all. all + yeterli min.insync.replicas ⇒ daha güvenli.
  • Consumer Group → Paralel okuma + ölçek; her partition bir consumer’a.
  • Retention (süre/boyut) & Log Compaction (son değer saklama).

Partisyonlama & Ordering

  • Ordering partisyon içinde garanti; aynı anahtar → aynı partisyon.
  • Hot partition riskine dikkat; key seçimini dengeli yap.

✉️ Producer — Ayarlar & Kod

Önemli Ayarlar

AyarÖneriEtki
acksallDayanıklılık
enable.idempotencetrueDuplikasyon engeli
retriesyüksekGeçici hata toleransı
linger.ms5–50Batching/Throughput
batch.size32–128 KBBatching
compression.typelz4/zstdAğ/Depolama
// Vanilla Producer (idempotent + acks=all)
Properties p = new Properties();
p.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka:9092");
p.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
p.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
p.put(ProducerConfig.ACKS_CONFIG, "all");
p.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true");
p.put(ProducerConfig.LINGER_MS_CONFIG, "20");
p.put(ProducerConfig.BATCH_SIZE_CONFIG, 65536);

try (var producer = new KafkaProducer<String,String>(p)) {
  var rec = new ProducerRecord<String,String>("orders", "user-42", "{\"id\":123}");
  producer.send(rec).get(); // senkron bekleme örnek (demo)
}
// Transactional Producer (read-process-write zinciri için)
p.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG, "order-tx-1");
var producer = new KafkaProducer<String,String>(p);
producer.initTransactions();
try {
  producer.beginTransaction();
  // kaynak topic'ten okunan offset'leri de transaction'a include et (consumer tarafı ile birlikte)
  producer.send(new ProducerRecord<>("orders-validated", key, value));
  // producer.sendOffsetsToTransaction(consumerOffsets, groupId);
  producer.commitTransaction();
} catch (Exception e) {
  producer.abortTransaction();
}

📬 Consumer & Rebalance

Poll Döngüsü & Commit

Properties c = new Properties();
c.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka:9092");
c.put(ConsumerConfig.GROUP_ID_CONFIG, "billing");
c.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
c.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
c.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
c.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, "500");

var consumer = new KafkaConsumer<String,String>(c);
consumer.subscribe(List.of("orders"));

while (true) {
  var records = consumer.poll(Duration.ofSeconds(1));
  for (var r : records) {
    // işlem...
  }
  consumer.commitSync(); // en az bir kez (at-least-once)
}
  • max.poll.interval.ms’i iş sürene göre ayarla, aksi hâlde rebalance olur.
  • Sticky/cooperative rebalance tüketici kararlılığını artırır.

Spring Kafka Notları

  • @KafkaListener ile tüketim; DefaultErrorHandler + DeadLetterPublishingRecoverer ile DLT.
  • Container ackMode: record, batch, manual
@KafkaListener(topics = "orders", groupId = "billing")
public void onMessage(ConsumerRecord<String, String> rec) {
  // işlem...
  // @Transactional ile DB + Kafka işlemlerini kapsamak mümkün (dikkat: EOS tasarımı)
}

🧪 Exactly-Once Semantics (EOS)

Yaklaşımlar

  • Idempotent Producer: Aynı kaydı bir kez yazılmış gibi görünmesini sağlar (topic içinde).
  • Transactional Producer: Birden fazla topic’e atomik yazma + okunan offset’lerin atomik commit’i.
  • Outbox Pattern: Uygulama DB’sine outbox tabloya yaz, CDC (Debezium) ile Kafka’ya akıt → DB & Kafka arasında tek transaction.

Doğru Modeli Seç

  • DB yaz + Kafka üret (aynı işlemde ihtiyacı): Outbox en güvenli pratik.
  • Kafka → Kafka akışlarında: Transactional producer (read-process-write) uygun.
  • EOS, throughput’u azaltabilir; ölç ve sınırları bil.

🛡️ Retry, DLT, Backoff & Ordering

Desenler

  • Retry Topic: Zaman gecikmeli topic zinciri (örn. orders.retry.5sorders.retry.1m → DLT).
  • DLT (Dead Letter Topic): Sürekli hata veren kayıtları izole et.
  • Backoff: Exponential + jitter (thundering herd’i önle).
  • Ordering: Aynı anahtar için aynı partisyonu koru; DLT’ye anahtarı bozmadan gönder.
// Spring Kafka - DLT yayımcısı (özet)
@Bean
DefaultErrorHandler errorHandler(KafkaTemplate<Object, Object> tpl) {
  var recoverer = new DeadLetterPublishingRecoverer(tpl);
  var eh = new DefaultErrorHandler(recoverer, new ExponentialBackOffWithMaxRetries(3));
  return eh;
}

🌊 Kafka Streams — Kısa Bakış

  • KStream (akış), KTable (durum) ve State Store (RocksDB).
  • Exactly-once processing (processing.guarantee = exactly_once_v2).
Properties p = new Properties();
p.put(StreamsConfig.APPLICATION_ID_CONFIG, "orders-app");
p.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka:9092");
p.put(StreamsConfig.PROCESSING_GUARANTEE_CONFIG, StreamsConfig.EXACTLY_ONCE_V2);

StreamsBuilder b = new StreamsBuilder();
KStream<String,String> orders = b.stream("orders");
orders.filter(/* ... */).to("orders-validated");
KafkaStreams s = new KafkaStreams(b.build(), p); s.start();

❓ Mülakat Soruları & Kısa Yanıtlar

1) Cache-aside nedir, riskleri?

Önce cache kontrolü, miss’te DB → cache. Risk: Invalidation zorluğu, stampede.

2) Redis eviction politikaları?

allkeys-lru, volatile-ttl, allkeys-random… Kullanım senaryosuna göre seç.

3) Hot key nasıl çözülür?

Replika/near cache, anahtarı parçala, isteklere jitter, local cache warmup.

4) Kafka’da ordering nasıl korunur?

Aynı key için aynı partisyon; concurrency’yi partisyon sayısı belirler.

5) acks=all ne sağlar?

Lider + yeterli ISR onayıyla dayanıklılık. min.insync.replicas ile birlikte düşün.

6) Exactly-once nasıl?

Idempotent + transactional producer; ya da Outbox + CDC ile DB–Kafka tek transaction.

7) DLT ne işe yarar?

Sürekli hatalı kayıtları izole eder; operasyonel gözlem ve sonradan yeniden oynatma.

8) Log compaction nedir?

Aynı key’in yalnızca son sürümünü tutar; durum temsili akışlar için idealdir.

9) Spring Cache’de TTL nasıl ayarlanır?

RedisCacheManager üzerinde entryTtl veya cache-spec bazlı konfig.

10) Rebalance neden olur, nasıl azaltılır?

Consumer ekleme/çıkarma, uzun işlem süreleri. max.poll.interval.ms ayarı, cooperative balancing.