Il caching di memoria (spesso chiamato semplicemente caching) è una tecnica in cui le applicazioni per computer memorizzano temporaneamente i dati nella memoria principale di un computer (ad esempio, memoria ad accesso casuale o RAM) per consentire il recupero rapido di tali dati. La RAM utilizzata per l’archiviazione temporanea è nota come cache. Poiché l’accesso alla RAM è significativamente più veloce rispetto all’accesso ad altri supporti come dischi rigidi o reti, il caching aiuta le applicazioni a funzionare più velocemente a causa di un accesso più rapido ai dati. La memorizzazione nella cache è particolarmente efficiente quando l’applicazione presenta uno schema comune in cui accede ripetutamente ai dati a cui è stato precedentemente effettuato l’accesso. La memorizzazione nella cache è utile anche per memorizzare calcoli di dati che altrimenti richiedono molto tempo per il calcolo. Memorizzando i calcoli in una cache, il sistema consente di risparmiare tempo evitando la ripetizione del calcolo.
Come funziona il caching della memoria?
La cache di memoria funziona prima mettendo da parte una porzione di RAM da utilizzare come cache. Quando un’applicazione tenta di leggere i dati, in genere da un sistema di archiviazione dati come un database, verifica se il record desiderato esiste già nella cache. Se lo fa, l’applicazione leggerà i dati dalla cache, eliminando così l’accesso più lento al database. Se il record desiderato non è nella cache, l’applicazione legge il record dall’origine. Quando recupera i dati, scrive anche i dati nella cache in modo che quando l’applicazione ha bisogno degli stessi dati in futuro, possa ottenerli rapidamente dalla cache.
Poiché la cache è di dimensioni limitate, alla fine alcuni dati già nella cache dovranno essere rimossi per fare spazio a nuovi dati a cui l’applicazione ha avuto accesso più di recente. Ciò significa che il sistema di caching ha bisogno di una strategia su cui i record da rimuovere per fare spazio. La strategia dipenderà dalla natura degli accessi ai dati dell’applicazione e generalmente tenterà di rimuovere i record a cui non è previsto un nuovo accesso presto. Ad esempio, una strategia LRU (Least-Recently-Used) rimuoverà il record il cui ultimo accesso era prima di qualsiasi altro record nella cache. L’ipotesi qui è che se è passato molto tempo da quando è stato effettuato l’accesso al record, probabilmente non sarà possibile accedervi di nuovo presto. O per dirla in un altro modo, i record che sono stati più utilizzati di recente sarà probabilmente utilizzato di nuovo presto. Una strategia LFU (Least-Frequently-Used) comporta il monitoraggio del numero di accessi di ciascun record nella cache e la rimozione del record con il minor numero di accessi. L’ipotesi qui è che un record usato raramente non verrà probabilmente utilizzato di nuovo presto.
La sfida con le cache è come ridurre al minimo gli “errori di cache”, cioè, tentato legge dall’applicazione per record che non sono nella cache. Se hai troppi errori, l’efficienza della tua cache diminuisce. Un’applicazione che legge solo nuovi dati non trarrebbe beneficio da una cache e, di fatto, mostrerebbe prestazioni inferiori a causa del lavoro extra di controllo della cache che non trova ancora il record desiderato. Un modo in cui questa sfida può essere mitigata è sfruttando cache più grandi. Questo spesso non è pratico su un singolo computer, motivo per cui le cache distribuite sono scelte popolari per accelerare le applicazioni che devono accedere a set di dati più grandi. Una cache distribuita raggruppa la RAM di più computer collegati in un cluster in modo da poter creare una cache più grande che può continuare a crescere aggiungendo più computer al cluster. Tecnologie come Hazelcast IMDG possono essere utilizzate come cluster distribuiti per accelerare applicazioni su larga scala.
Un’altra sfida delle cache è il rischio di leggere dati “obsoleti”, in cui i dati nella cache non riflettono i dati più recenti nell’origine sottostante. Spesso questo rischio è un compromesso accettabile per le prestazioni dell’applicazione. Nei casi in cui non lo è, spetta all’applicazione che aggiorna l’origine dati sottostante aggiornare il record in questione nella cache.
Casi d’uso di esempio
Un ampio caso d’uso per il caching della memoria è quello di accelerare le applicazioni di database, in particolare quelle che eseguono molte letture di database. Sostituendo una porzione di letture del database con letture dalla cache, le applicazioni possono rimuovere la latenza derivante da frequenti accessi al database. Questo caso d’uso si trova in genere in ambienti in cui viene visualizzato un volume elevato di accessi ai dati, come in un sito Web ad alto traffico che presenta contenuti dinamici da un database.
Un altro caso d’uso comporta l’accelerazione della query, in cui i risultati di una query complessa a un database vengono memorizzati nella cache. Le query complesse che eseguono operazioni come il raggruppamento e l’ordine possono richiedere molto tempo per essere completate. Se le query vengono eseguite ripetutamente, come nel caso di un dashboard di business intelligence (BI) a cui si accede da molti utenti, la memorizzazione dei risultati in una cache consentirebbe una maggiore reattività in tali dashboard.
Argomenti correlati
JCache / Java Cache
Cache Miss
Hibernate Second-Level Cache
Ulteriori letture
Caching Use Case
Database Caching
Hazelcast Cloud
Caching fatto Bootiful: Spring Cache + Hazelcast