Skip to main content

Sorun: L1 her node’da ayrı

HybridCache’in L2’si (Redis) paylaşımlıdır — tüm node’lar aynı Redis’i görür, tag mark’ı herkesçe okunur. Ancak L1 (in-process memory) her node’da ayrıdır. Bir node tag’i düşürüp kendi L1’ini temizlese de, diğer node’ların L1’inde aynı veri TTL dolana kadar bayat kalır. Çözüm: bir node tag düşürdüğünde EventBus üzerinden diğer node’lara haber verip onların da sadece L1’lerini düşürmesini sağlamak.

EventBusRemoteTagBroadcaster

IRemoteTagBroadcaster’ın EventBus (MassTransit + RabbitMQ) backend’li implementasyonu (src/.../Application/SeedWork/Caching/EventBusRemoteTagBroadcaster.cs). IHybridRequestCache.RemoveByTagAsync içinden, BroadcastTagInvalidation açıksa tetiklenir.
Lifetime deseni: IHybridRequestCache Singleton, dolayısıyla broadcaster da Singleton; ama IEventBus Scoped. Bu yüzden ctor injection yerine IServiceScopeFactory tutulup her broadcast’te scope açılır — standart “Singleton consumes Scoped” pattern’i. Tag invalidation seyrek olduğu için maliyet düşük.
NodeId bilerek static’tir: aynı process içinde hem broadcaster (publish) hem handler (consume) aynı değeri okur — echo tespiti bunun üzerine kuruludur.

CacheInvalidationIntegrationEvent

Yayınlanan event (src/BuildingBlocks/.../Contracts.Events/Cache/CacheInvalidationIntegrationEvent.cs):

Echo guard + cascade önleme

Receiver CacheInvalidationIntegrationEventHandler (src/.../Application/IntegrationEventHandlers/CacheInvalidation/) iki önlem taşır:

Konfigürasyon

Broadcaster registration: BuildingBlocks.Caching.AddCache default olarak NoopRemoteTagBroadcaster’ı TryAdd ile koyar. Application katmanı EventBus aktifken bunu gerçek impl ile Replace eder (AddSingleton, TryAdd değil):

İlgili

Invalidation

RemoveByTagAsync vs RemoveByTagLocallyAsync.

Integration Events

IntegrationEvent base ve consumer kaydı.

RabbitMQ Topology

Exchange, routing key, queue.

Cache Mimarisi

Genel bakış.