Nella progettazione di sistemi ad alte prestazioni, la gestione dell'eviction - ossia decidere quale dato eliminare quando la cache è piena - è tanto cruciale quanto la scelta stessa della cache (Redis, Memcached, Guava, ecc.) L'immagine qui sotto riassume le principali politiche di cache adottabili. Sarebbe bene averle sempre presente, perché comprenderle in profondità significa capire quale modello di accesso ai dati stiamo ottimizzando.

Schema delle sette principali politiche di cache eviction: LRU, LFU, MRU, TTL, FIFO, Random Replacement e two-tiered caching

1. Least Recently Used (LRU)

Evicte il dato meno recentemente utilizzato. È la politica più comune perché riflette un principio empirico: i dati usati di recente tendono a essere riutilizzati presto. Bassa complessità, con strutture come LinkedHashMap o deque + hash map e buon compromesso tra semplicità e efficacia. Può tuttavia degradare con accessi sequenziali (effetto thrashing).

2. Least Frequently Used (LFU)

Rimuove l'elemento meno frequentemente usato nel tempo. Computazionalmente più "costoso" da mantenere, ma più accurato nei workload stabili. È quindi ideale per dataset con alta località di frequenza (es. "hot keys" persistenti). Items popolari in passato possono restare troppo a lungo.

3. Most Recently Used (MRU)

Evicte l'elemento usato più di recente. Può sembrare controintuitivo, ma in realtà funziona bene in contesti dove i dati vengono acceduti una sola volta, ad esempio con query stream o scansioni di grandi dataset. È il tipico evicte per buffer temporanei o caching di streaming.

4. Time To Live (TTL)

Ogni oggetto ha una data di scadenza. L'eviction non dipende né dal tempo d'uso né dalla frequenza, ma dal tempo assoluto. Ideale per dati time-sensitive (token, configurazioni dinamiche di accesso, API cache). Spesso viene combinato con LRU o LFU per comportamenti più robusti.

5. First In, First Out (FIFO)

Elimina il primo elemento inserito. È semplice e deterministico, ma ignora completamente i pattern di accesso, ragion per cui può diventare inefficiente in carichi non sequenziali. Usato se e dove la prevedibilità è più importante delle performance.

6. Random Replacement (RR)

Sceglie a caso quale oggetto rimuovere. Apparentemente ingenuo, ma utile in sistemi estremamente dinamici o distribuiti dove il costo di mantenere metadati di accesso è troppo alto. Talvolta è usato come fallback o in hardware cache L1/L2 per minimizzare lock contention.

7. Two-Tiered Caching

Divide i dati in livelli: un tier "freddo" (es. disco o cloud) e uno "caldo" (RAM). Include politiche di promozione tra i livelli ed è perfetto per workload con località mista o dataset di dimensioni molto superiori alla memoria disponibile.

La cache quindi non è solo un buffer, ma un predittore del comportamento futuro basato su pattern passati. Sarebbe interessante delegare all'AI la gestione completa e ibrida della cache, per creare un "modello cognitivo delle politiche di data-eviction" (cold start + meta-learning).

#cache #AI