Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo modello carica i dati su richiesta in una cache da un archivio dati. Usare questo modello per migliorare le prestazioni e mantenere la coerenza tra i dati in una cache e i dati in un archivio dati sottostante.
Contesto e problema
Le applicazioni usano una cache per migliorare le prestazioni per l'accesso ripetuto alle informazioni in un archivio dati. Tuttavia, i dati memorizzati nella cache non sempre possono rimanere coerenti con l'archivio dati. Le applicazioni devono implementare una strategia che mantenga i dati nella cache il più possibile up-to-date. La strategia deve anche rilevare quando i dati memorizzati nella cache diventano obsoleti e gestirli in modo appropriato.
Soluzione
Molti sistemi di memorizzazione nella cache commerciali forniscono operazioni di lettura e scrittura write-through o write-behind. In questi sistemi un'applicazione fa riferimento alla cache per recuperare i dati. Se i dati non si trovano nella cache, l'applicazione lo recupera dall'archivio dati e lo aggiunge alla cache. Il sistema scrive automaticamente tutte le modifiche apportate ai dati memorizzati nella cache nell'archivio dati.
Per le cache che non forniscono questa funzionalità, le applicazioni che usano la cache devono gestire i dati.
Un'applicazione può emulare la funzionalità di caching read-through implementando il pattern Cache-Aside. Con questa strategia i dati vengono caricati nella cache su richiesta. Il diagramma seguente usa il modello di Cache-Aside per archiviare i dati nella cache.
L'applicazione determina se un elemento attualmente risiede nella cache tentando di leggere dalla cache.
Se l'elemento non è presente nella cache, noto anche come mancata memorizzazione nella cache, l'applicazione recupera l'elemento dall'archivio dati.
L'applicazione aggiunge l'elemento alla cache e lo restituisce al chiamante.
Se un'applicazione aggiorna le informazioni, può seguire la strategia di scrittura apportando la modifica all'archivio dati e invalidando l'elemento corrispondente nella cache.
Quando l'elemento è necessario di nuovo, il modello di Cache-Aside recupera i dati aggiornati dall'archivio dati e lo aggiunge alla cache.
Problemi e considerazioni
Quando si decide come implementare questo modello, tenere presente quanto segue:
Durata dei dati memorizzati nella cache: Molte cache usano un criterio di scadenza per invalidare i dati e rimuoverli dalla cache se non è accessibile per un periodo impostato. Per rendere effettiva la cache-aside, assicurarsi che i criteri di scadenza corrispondano al modello di accesso per le applicazioni che usano i dati. Non rendere troppo breve il periodo di scadenza perché la scadenza prematura può causare continuamente il recupero dei dati dall'archivio dati e l'aggiunta alla cache da parte delle applicazioni. Analogamente, non rendere il periodo di scadenza così lungo che i dati memorizzati nella cache diventino obsoleti. La memorizzazione nella cache funziona meglio per dati relativamente statici o dati letti di frequente da applicazioni.
Rimozione dei dati: La maggior parte delle cache ha una dimensione limitata rispetto all'archivio dati in cui hanno origine i dati. Se la cache supera il limite di dimensioni, rimuove i dati. La maggior parte delle cache adotta un criterio usato meno di recente per selezionare gli elementi per la rimozione, ma alcuni consentono la personalizzazione.
Configurazione: È possibile configurare il comportamento della cache a livello globale o per ogni elemento memorizzato nella cache. Un singolo criterio di rimozione globale potrebbe non essere adatto a tutti gli elementi. Se un elemento è costoso da recuperare, configurare singolarmente l'elemento della cache. In questo caso, è opportuno mantenere l'elemento nella cache, anche se viene eseguito l'accesso meno frequentemente rispetto agli elementi più economici.
Popolamento della cache: Molte soluzioni popolano la cache con dati che è probabile che un'applicazione richieda come parte del processo di avvio. Il modello di Cache-Aside rimane utile quando alcuni di questi dati scadono o vengono rimossi.
Coerenza: Il modello di Cache-Aside non garantisce la coerenza tra l'archivio dati e la cache. Ad esempio, un processo esterno può modificare un elemento nell'archivio dati in qualsiasi momento. Questa modifica non viene visualizzata nella cache finché l'elemento non viene caricato di nuovo. In un sistema che replica i dati tra archivi dati, la sincronizzazione frequente può rendere difficile la coerenza.
Memorizzazione nella cache locale: Una cache può essere locale a un'istanza dell'applicazione e archiviata in memoria. Cache-aside funziona bene in questo ambiente se un'applicazione accede ripetutamente agli stessi dati. Tuttavia, una cache locale è privata, quindi istanze dell'applicazione diverse possono avere una copia degli stessi dati memorizzati nella cache. Questi dati possono diventare rapidamente incoerenti tra le cache, quindi potrebbe essere necessario scadere i dati in una cache privata e aggiornarli più frequentemente. In questi scenari è consigliabile usare un meccanismo di memorizzazione nella cache condivisa o distribuita.
Memorizzazione nella cache semantica: Alcuni carichi di lavoro possono trarre vantaggio dall'eseguire il recupero della cache in base al significato semantico anziché alle chiavi esatte. Questo approccio riduce il numero di richieste e token inviati ai modelli linguistici. Usare la memorizzazione nella cache semantica solo quando i dati supportano l'equivalenza semantica, non rischia di restituire risposte non correlate e non contiene dati privati e sensibili. Ad esempio, "Qual è il mio stipendio netto annuale?" è semanticamente simile a "Qual è il mio salario netto annuale?" Ma se utenti diversi pongono queste domande, le risposte dovrebbero differire. Non è inoltre consigliabile includere questi dati sensibili nella cache.
Quando usare questo modello
Usare questo modello quando:
Una cache non offre operazioni native di read-through e write-through.
La richiesta di risorse è imprevedibile. Questo modello consente alle applicazioni di caricare dati su richiesta. Non presuppone i dati richiesti in anticipo da un'applicazione.
Questo modello potrebbe non essere adatto quando:
I dati sono sensibili o correlati alla sicurezza. L'archiviazione dei dati in una cache potrebbe non essere appropriata, soprattutto quando più applicazioni o utenti condividono la cache. Recuperare sempre questo tipo di dati dall'origine primaria.
Il set di dati memorizzato nella cache è statico. Se i dati rientrano nello spazio della cache disponibile, primere la cache con i dati all'avvio e applicare un criterio che impedisce la scadenza dei dati.
La maggior parte delle richieste non riscontra un riscontro nella cache. In questo caso, il sovraccarico di controllo della cache e del caricamento dei dati in potrebbe superare i vantaggi della memorizzazione nella cache.
Le informazioni sullo stato della sessione sono memorizzate nella cache in un'applicazione Web ospitata in una web farm. In questo ambiente evitare di introdurre dipendenze basate sull'affinità client-server.
Progettazione del carico di lavoro
Valutare come usare il modello di Cache-Aside nella progettazione di un carico di lavoro per soddisfare gli obiettivi e i principi trattati nei pilastri di Azure Well-Architected Framework. La tabella seguente fornisce indicazioni su come questo modello supporta gli obiettivi di ogni pilastro.
| Pilastro | Come questo modello supporta gli obiettivi di pilastro |
|---|---|
| decisioni di progettazione dell'affidabilità consentono al carico di lavoro di diventare resiliente a un malfunzionamento e assicurano che ripristini a uno stato completamente funzionante dopo che si verifica un guasto. | La memorizzazione nella cache replica i dati. In modi limitati, può mantenere la disponibilità dei dati a cui si accede di frequente se l'archivio dati di origine diventa temporaneamente non disponibile. Se la cache non funziona correttamente, il carico di lavoro può ritornare all'archivio dati di origine. - Ridondanza RE:05 |
| l'efficienza delle prestazioni consente al carico di lavoro soddisfare in modo efficiente le richieste tramite ottimizzazioni di ridimensionamento, dati e codice. | La memorizzazione nella cache migliora le prestazioni per i dati con un numero elevato di letture che cambiano raramente e tollera un certo decadimento. - Prestazioni dei dati PE:08 - Ottimizzazione continua delle prestazioni PE:12 |
Se questo modello introduce compromessi all'interno di un pilastro, considerarli contro gli obiettivi degli altri pilastri.
Esempio
Prendere in considerazione l'uso di Redis gestito di Azure per creare una cache distribuita che più istanze dell'applicazione possono condividere.
L'esempio seguente usa il client StackExchange.Redis , ovvero una libreria client Redis scritta per .NET. Per connettersi a un'istanza di Redis gestita di Azure, chiamare il metodo statico ConnectionMultiplexer.Connect e passare la stringa di connessione. Il metodo restituisce un elemento ConnectionMultiplexer che rappresenta la connessione.
Un modo per condividere un'istanza nell'applicazione consiste nell'avere una ConnectionMultiplexer proprietà statica che restituisce un'istanza connessa, simile all'esempio seguente. Questo approccio costituisce un modo thread-safe per inizializzare solo una singola istanza connessa.
private static ConnectionMultiplexer Connection;
// Redis connection string information
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
string cacheConnection = ConfigurationManager.AppSettings["CacheConnection"].ToString();
return ConnectionMultiplexer.Connect(cacheConnection);
});
public static ConnectionMultiplexer Connection => lazyConnection.Value;
Il GetMyEntityAsync metodo nell'esempio seguente mostra un'implementazione del modello di Cache-Aside. Questo metodo recupera un oggetto dalla cache usando l'approccio read-through.
Il metodo identifica un oggetto utilizzando un ID intero come chiave. Tenta di recuperare un elemento dalla cache usando questa chiave. Se la cache contiene un elemento corrispondente, restituisce l'elemento. Se la cache non contiene una corrispondenza, il GetMyEntityAsync metodo recupera l'oggetto da un archivio dati, lo aggiunge alla cache e quindi lo restituisce. In questo esempio viene omesso il codice che legge i dati dall'archivio dati perché tale logica dipende dall'archivio dati. L'elemento memorizzato nella cache è configurato per scadere per impedire che diventi obsoleto se un altro servizio o lo aggiorna.
// Set five minute expiration as a default
private const double DefaultExpirationTimeInMinutes = 5.0;
public async Task<MyEntity> GetMyEntityAsync(int id)
{
// Define a unique key for this method and its parameters.
var key = $"MyEntity:{id}";
var cache = Connection.GetDatabase();
// Try to get the entity from the cache.
var json = await cache.StringGetAsync(key).ConfigureAwait(false);
var value = string.IsNullOrWhiteSpace(json)
? default(MyEntity)
: JsonConvert.DeserializeObject<MyEntity>(json);
if (value == null) // Cache miss
{
// If there's a cache miss, get the entity from the original store and cache it.
// Code has been omitted because it is data store dependent.
value = ...;
// Avoid caching a null value.
if (value != null)
{
// Put the item in the cache with a custom expiration time that
// depends on how critical it is to have stale data.
await cache.StringSetAsync(key, JsonConvert.SerializeObject(value)).ConfigureAwait(false);
await cache.KeyExpireAsync(key, TimeSpan.FromMinutes(DefaultExpirationTimeInMinutes)).ConfigureAwait(false);
}
}
return value;
}
Nota
Gli esempi usano Redis gestito di Azure per accedere all'archivio e recuperare informazioni dalla cache. Per altre informazioni, vedere Creare un'istanza di Redis gestita di Azure e Usare Redis gestito di Azure in .NET Core.
Il metodo seguente UpdateEntityAsync illustra come invalidare un oggetto nella cache quando l'applicazione modifica il valore. Il codice aggiorna l'archivio dati originale e quindi rimuove dalla cache l'elemento memorizzato nella cache.
public async Task UpdateEntityAsync(MyEntity entity)
{
// Update the object in the original data store.
await this.store.UpdateEntityAsync(entity).ConfigureAwait(false);
// Invalidate the current cache object.
var cache = Connection.GetDatabase();
var id = entity.Id;
var key = $"MyEntity:{id}"; // The key for the cached object.
await cache.KeyDeleteAsync(key).ConfigureAwait(false); // Delete this key from the cache.
}
Nota
L'ordine dei passaggi è importante. Aggiornare l'archivio dati prima di rimuovere l'elemento dalla cache. Se si rimuove prima di tutto l'elemento memorizzato nella cache, si verifica un piccolo intervallo di tempo in cui un client potrebbe recuperare l'elemento prima dell'aggiornamento dell'archivio dati. In questo caso, il recupero genera un mancato riscontro nella cache perché l'elemento non si trova nella cache. Il mancato riscontro nella cache fa sì che l'applicazione recuperi l'elemento obsoleto dall'archivio dati e lo aggiunga alla cache. Questa sequenza porta a dati non aggiornati nella cache.
Passaggi successivi
Nozioni di base sulla coerenza dei dati: questa guida di base descrive i problemi di coerenza tra i dati distribuiti. Viene inoltre riepilogato il modo in cui un'applicazione può implementare la coerenza finale per mantenere la disponibilità dei dati. Le applicazioni cloud in genere archiviano i dati in più archivi dati e posizioni. È necessario gestire e mantenere in modo efficiente la coerenza dei dati in questo ambiente, in particolare a causa di problemi di concorrenza e disponibilità che possono verificarsi.
Usare Redis gestito di Azure come cache semantica: questa esercitazione illustra come implementare la memorizzazione nella cache semantica usando Azure Managed Redis.
Risorse correlate
Modello di app Web affidabile: questo modello applica il modello di Cache-Aside alle applicazioni Web nel cloud.
Indicazioni sulla memorizzazione nella cache: queste indicazioni forniscono altre informazioni su come memorizzare nella cache i dati in una soluzione cloud e sui problemi da considerare quando si implementa una cache.