⚡ 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
| Tip | Kullanım | Örnek |
|---|---|---|
| String | Basit cache (JSON), sayaç | SET user:42 {...} |
| Hash | Alan bazlı kısmi güncelle | HSET sess:abc user 42 ttl 3600 |
| List | Queue, recent items | LPUSH recent:log ... |
| Set | Benzersiz topluluk | SADD online:users 42 |
| ZSet | Sıralı veri, leaderboard | ZADD rank 100 "neo" |
| Bitmap/HyperLogLog | A/B, tahmini sayım | PFADD uv:2024 user42 |
TTL & Eviction
EXPIRE key 60,PERSISTTTL’i kaldırır.- Eviction politikaları:
volatile-lru,allkeys-lru,volatile-ttl,allkeys-random…
| Politika | Açıklama | Ne zaman? |
|---|---|---|
| allkeys-lru | En az kullanılanı at | Global LRU, TTL olmasa da |
| volatile-ttl | TTL’i en yakın olanı at | Hepsi TTL’li ise |
| allkeys-random | Rastgele at | Basit/ö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 | Özellik | Artı/Eksi |
|---|---|---|
| Cache-Aside | Önce cache’e bak; yoksa DB, sonra cache’e yaz | Basit / Invalidation zor |
| Write-Through | Yazma yolunda cache | Tutarlılık iyi / Yazma gecikmesi |
| Write-Behind | Önce cache, sonra async DB | Performans / Veri kaybı riski |
| Read-Through | Cache miss’te otomatik load | Kod 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
- Topic → Partition’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+ yeterlimin.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 | Öneri | Etki |
|---|---|---|
acks | all | Dayanıklılık |
enable.idempotence | true | Duplikasyon engeli |
retries | yüksek | Geçici hata toleransı |
linger.ms | 5–50 | Batching/Throughput |
batch.size | 32–128 KB | Batching |
compression.type | lz4/zstd | Ağ/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ı
@KafkaListenerile 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
outboxtabloya 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.5s→orders.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.