Cache-Aside-patroon

Azure Managed Redis

Met dit patroon worden gegevens op aanvraag in een cache geladen vanuit een gegevensarchief. Gebruik dit patroon om de prestaties te verbeteren en consistentie tussen gegevens in een cache en gegevens in een onderliggende gegevensopslag te behouden.

Context en probleem

Toepassingen gebruiken een cache om de prestaties te verbeteren voor herhaalde toegang tot informatie in een gegevensarchief. Maar in de cache opgeslagen gegevens kunnen niet altijd consistent blijven met het gegevensarchief. Toepassingen moeten een strategie implementeren waarmee de gegevens in de cache zo up-to-date mogelijk worden bewaard. De strategie moet ook detecteren wanneer de gegevens in de cache niet meer actueel zijn en deze op de juiste wijze afhandelen.

Oplossing

Veel commerciële cachingsystemen bieden lees- en write-through- of write-behind-bewerkingen. In deze systemen worden de gegevens opgehaald door naar de cache te verwijzen. Als de gegevens zich niet in de cache bevinden, haalt de toepassing deze op uit het gegevensarchief en voegt deze toe aan de cache. Het systeem schrijft automatisch eventuele wijzigingen in de cachegegevens terug naar het gegevensarchief.

Voor caches die deze functionaliteit niet bieden, moeten de toepassingen die gebruikmaken van de cache de gegevens onderhouden.

Een toepassing kan de functionaliteit van read-through caching emuleren door het Cache-Aside patroon te implementeren. Met deze strategie worden gegevens op verzoek in de cache geladen. In het volgende diagram wordt het Cache-Aside patroon gebruikt om gegevens op te slaan in de cache.

Diagram met het gebruik van het Cache-Aside patroon voor het lezen en opslaan van gegevens in de cache.

  1. De toepassing bepaalt of een item zich momenteel in de cache bevindt door uit de cache te lezen.

  2. Als het item zich niet in de cache bevindt, ook wel een cachemisser genoemd, haalt de toepassing het item op uit het gegevensarchief.

  3. De toepassing voegt het item toe aan de cache en retourneert het vervolgens aan de aanroeper.

Als een toepassing informatie bijwerken, kan deze de write-through-strategie volgen door de wijziging aan te passen aan het gegevensarchief en het bijbehorende item in de cache ongeldig te maken.

Wanneer het item opnieuw nodig is, haalt het Cache-Aside patroon de bijgewerkte gegevens op uit het gegevensarchief en voegt het toe aan de cache.

Problemen en overwegingen

Houd rekening met de volgende punten wanneer u besluit hoe u dit patroon implementeert:

  • Levensduur van gegevens in de cache: Veel caches gebruiken een verloopbeleid om gegevens ongeldig te maken en te verwijderen uit de cache als deze gedurende een bepaalde periode niet worden geopend. Als u cache-aside effectief wilt maken, moet u ervoor zorgen dat het verloopbeleid overeenkomt met het patroon van toegang voor toepassingen die gebruikmaken van de gegevens. Maak de verloopperiode niet te kort omdat voortijdige vervaldatum ertoe kan leiden dat toepassingen voortdurend gegevens ophalen uit het gegevensarchief en deze toevoegen aan de cache. Zorg er ook niet voor dat de verloopperiode zo lang is dat de gegevens in de cache verouderen. Caching werkt het beste voor relatief statische gegevens of gegevens die toepassingen regelmatig lezen.

  • Gegevens wissen: De meeste caches hebben een beperkte grootte vergeleken met het gegevensarchief waar de gegevens vandaan komen. Als de cache de maximale grootte overschrijdt, worden gegevens verwijderd. De meeste caches gebruiken een minst recent gebruikt beleid om items te selecteren voor verwijdering, maar sommige toestaan aanpassingen.

  • Configuratie: U kunt het cachegedrag globaal of per item in de cache configureren. Eén globaal verwijderingsbeleid is mogelijk niet geschikt voor alle items. Als een item duur is om op te halen, configureert u het cache-item afzonderlijk. In deze situatie is het zinvol om het item in de cache te houden, zelfs als het minder vaak wordt geopend dan goedkopere items.

  • De cache voorbereiden: Veel oplossingen vullen de cache vooraf in met gegevens die een toepassing waarschijnlijk nodig heeft als onderdeel van de opstartverwerking. Het Cache-Aside patroon blijft nuttig wanneer sommige van deze gegevens verlopen of worden verwijderd.

  • Consistentie: Het Cache-Aside-patroon garandeert geen consistentie tussen het gegevensarchief en de cache. Een extern proces kan bijvoorbeeld op elk gewenst moment een item in het gegevensarchief wijzigen. Deze wijziging wordt pas in de cache weergegeven als het item opnieuw wordt geladen. In een systeem dat gegevens repliceert in gegevensarchieven, kan regelmatige synchronisatie een uitdaging vormen voor consistentie.

  • Lokale caching: Een cache kan lokaal zijn voor een toepassingsexemplaren en in het geheugen worden opgeslagen. Cache-aside werkt goed in deze omgeving als een toepassing herhaaldelijk toegang heeft tot dezelfde gegevens. Maar een lokale cache is privé, zodat verschillende toepassingsexemplaren elk een kopie van dezelfde gegevens in de cache kunnen hebben. Deze gegevens kunnen snel inconsistent worden tussen caches, dus mogelijk moet u gegevens in een privécache laten verlopen en deze vaker vernieuwen. In deze scenario's kunt u overwegen om een mechanisme voor gedeelde of gedistribueerde caching te gebruiken.

  • Semantische caching: Sommige workloads kunnen profiteren van het ophalen van caches op basis van semantische betekenis in plaats van exacte sleutels. Deze aanpak vermindert het aantal aanvragen en tokens dat naar taalmodellen wordt verzonden. Gebruik alleen semantische caching wanneer de gegevens semantische gelijkwaardigheid ondersteunen, risico lopen niet het retourneren van niet-gerelateerde antwoorden en bevatten geen privé- en gevoelige gegevens. Bijvoorbeeld, "Wat is mijn jaarlijkse netto salaris?" is semantisch vergelijkbaar met "Wat is mijn jaarlijkse netto inkomen?" Maar als verschillende gebruikers deze vragen stellen, zullen de antwoorden verschillen. U moet deze gevoelige gegevens ook niet opnemen in uw cache.

Wanneer dit patroon gebruiken

Gebruik dit patroon wanneer:

  • Een cache biedt geen systeemeigen read-through- en write-through-bewerkingen.

  • De vraag naar resources is onvoorspelbaar. Dit patroon stelt toepassingen in staat op aanvraag gegevens te laden. Er wordt niet van uitgegaan welke gegevens een toepassing vooraf vereist.

Dit patroon is mogelijk niet geschikt wanneer:

  • De gegevens zijn gevoelig of beveiligingsgerelateerd. Het opslaan van gegevens in een cache kan ongepast zijn, met name wanneer meerdere toepassingen of gebruikers de cache delen. Haal dit type gegevens altijd op uit de primaire bron.

  • De gegevensset in de cache is statisch. Als de gegevens in de beschikbare cacheruimte passen, moet u de cache primeren met de gegevens bij het opstarten en een beleid toepassen dat voorkomt dat de gegevens verlopen.

  • De meeste aanvragen ondervinden geen cachetreffer. In dit geval kan de overhead van het controleren van de cache en het laden van gegevens in de cache opwegen tegen de voordelen van caching.

  • U slaat sessiestatusgegevens op in een webtoepassing die wordt gehost in een webfarm. Vermijd in deze omgeving het introduceren van afhankelijkheden op basis van client-serveraffiniteit.

Workloadontwerp

Evalueer hoe u het Cache-Aside-patroon in het ontwerp van een workload kunt gebruiken om de doelstellingen en principes te verhelpen die worden behandeld in de pijlers van het Azure Well-Architected Framework. De volgende tabel bevat richtlijnen over hoe dit patroon de doelstellingen van elke pijler ondersteunt.

Pijler Hoe dit patroon ondersteuning biedt voor pijlerdoelen
betrouwbaarheid ontwerpbeslissingen helpen uw workload tolerant te worden defect te raken en ervoor te zorgen dat deze herstelt naar een volledig functionerende status nadat er een storing is opgetreden. In de cache worden gegevens gerepliceerd. Op beperkte manieren kan de beschikbaarheid van veelgebruikte gegevens behouden blijven als het oorspronkelijke gegevensarchief tijdelijk niet beschikbaar is. Als de cache defect is, kan de werkbelasting terugvallen op het oorspronkelijke gegevensarchief.

- RE:05 Redundantie
Prestatie-efficiëntie helpt uw workload efficiënt te voldoen aan de vereisten door middel van optimalisaties in schalen, gegevens en code. Caching verbetert de prestaties voor leesintensieve gegevens die zelden worden gewijzigd en die enkele veroudering tolereert.

- PE:08 Gegevensprestaties
- PE:12 Continue prestatieoptimalisatie

Als dit patroon compromissen binnen een pijler introduceert, moet u deze tegen de doelstellingen van de andere pijlers overwegen.

Voorbeeld

Overweeg het gebruik van Azure Managed Redis om een gedistribueerde cache te maken die meerdere toepassingsexemplaren kunnen delen.

In het volgende voorbeeld wordt de StackExchange.Redis-client gebruikt. Dit is een Redis-clientbibliotheek die is geschreven voor .NET. Als u verbinding wilt maken met een Azure Managed Redis-exemplaar, roept u de statische ConnectionMultiplexer.Connect methode aan en geeft u de verbindingsreeks door. Met deze methode wordt een ConnectionMultiplexer geretourneerd die de verbinding representeert.

Een manier om een ConnectionMultiplexer exemplaar in uw toepassing te delen, is door een statische eigenschap te hebben die een verbonden exemplaar retourneert, vergelijkbaar met het volgende voorbeeld. Deze benadering biedt een thread-veilige manier om slechts één verbonden exemplaar te initialiseren.

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;

De GetMyEntityAsync methode in het volgende voorbeeld toont een implementatie van het Cache-Aside patroon. Met deze methode wordt een object opgehaald uit de cache met behulp van de leesmethode.

De methode identificeert een object met behulp van een geheel getal-id als de sleutel. Er wordt geprobeerd een item op te halen uit de cache met behulp van deze sleutel. Als de cache een overeenkomend item bevat, wordt het item geretourneerd. Als de cache geen overeenkomst bevat, haalt de GetMyEntityAsync methode het object op uit een gegevensarchief, voegt deze toe aan de cache en retourneert het vervolgens. In dit voorbeeld wordt de code weggelaten waarmee de gegevens uit het gegevensarchief worden gelezen, omdat deze logica afhankelijk is van het gegevensarchief. Het item in de cache is zo geconfigureerd dat het verloopt om te voorkomen dat het verouderd wordt als een andere service of proces het bijwerkt.

// 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;
}

Notitie

In de voorbeelden wordt Azure Managed Redis gebruikt om toegang te krijgen tot het archief en informatie op te halen uit de cache. Zie Een Azure Managed Redis-exemplaar maken en Azure Managed Redis gebruiken in .NET Core voor meer informatie.

De volgende UpdateEntityAsync methode laat zien hoe u een object in de cache ongeldig maakt wanneer de toepassing de waarde wijzigt. Met de code wordt het oorspronkelijke gegevensarchief bijgewerkt en vervolgens wordt het item uit de cache verwijderd.

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.
}

Notitie

De volgorde van de stappen is belangrijk. Werk het gegevensarchief bij voordat u het item uit de cache verwijdert. Als u het item in de cache eerst verwijdert, is er een klein tijdvenster waarin een client het item kan ophalen voordat het gegevensarchief wordt bijgewerkt. In dit geval resulteert het ophalen in een cachemisser omdat het item zich niet in de cache bevindt. De cache-miss zorgt ervoor dat de toepassing het verouderde item uit de datastore ophaalt en weer toevoegt aan de cache. Deze reeks leidt tot verouderde gegevens in de cache.

Volgende stappen 

  • Primer voor gegevensconsistentie: in deze primer worden problemen met consistentie in gedistribueerde gegevens beschreven. Ook wordt samengevat hoe een toepassing uiteindelijke consistentie kan implementeren om de beschikbaarheid van gegevens te behouden. Cloudtoepassingen slaan doorgaans gegevens op in meerdere gegevensarchieven en locaties. U moet gegevensconsistentie in deze omgeving efficiënt beheren en onderhouden, met name vanwege gelijktijdigheids- en beschikbaarheidsproblemen die kunnen optreden.

  • Azure Managed Redis gebruiken als een semantische cache: in deze zelfstudie leert u hoe u semantische caching implementeert met behulp van Azure Managed Redis.

  • Betrouwbaar web-app-patroon: dit patroon past het Cache-Aside patroon toe op webtoepassingen in de cloud.

  • Richtlijnen voor caching: deze richtlijnen bieden meer informatie over het opslaan van gegevens in een cloudoplossing en problemen die u moet overwegen bij het implementeren van een cache.