Mönstret Cache-AsideCache-Aside pattern

Läs in data på begäran till en cache från ett datalager.Load data on demand into a cache from a data store. Det här kan förbättra prestanda och även bidra till att upprätthålla konsekvens mellan cachelagrade data och data i det underliggande datalagret.This can improve performance and also helps to maintain consistency between data held in the cache and data in the underlying data store.

Kontext och problemContext and problem

Program använder en cache för att förbättra upprepad åtkomst till information som lagras i ett datalager.Applications use a cache to improve repeated access to information held in a data store. Det är däremot opraktiskt att förvänta sig att cachelagrade data alltid är fullständigt konsekventa med de data som lagras i datalagret.However, it's impractical to expect that cached data will always be completely consistent with the data in the data store. Program bör implementera en strategi som bidrar till att säkerställa att cachelagrade data är så uppdaterade som möjligt, men att de också kan upptäcka och hantera situationer som uppstår när cachelagrade data har blivit inaktuella.Applications should implement a strategy that helps to ensure that the data in the cache is as up-to-date as possible, but can also detect and handle situations that arise when the data in the cache has become stale.

LösningSolution

Många kommersiella cachelagringssystem har åtgärder för genomläsning och genomskrivning/skrivning bakom.Many commercial caching systems provide read-through and write-through/write-behind operations. I de här systemen hämtar ett program data genom att referera till cachen.In these systems, an application retrieves data by referencing the cache. Om dina data inte finns i cacheminnet hämtas de från datalagret och läggs till i cachen.If the data isn't in the cache, it's retrieved from the data store and added to the cache. Ändringar av data som lagras i cachen skrivs också automatiskt tillbaka till dataarkivet.Any modifications to data held in the cache are automatically written back to the data store as well.

Program som bibehåller data med cachen ansvarar inte för cache som inte har den här funktionen.For caches that don't provide this functionality, it's the responsibility of the applications that use the cache to maintain the data.

Ett program kan emulera funktionerna för cachelagring av genomläsning genom att implementera en strategi för cache-aside.An application can emulate the functionality of read-through caching by implementing the cache-aside strategy. Den här strategin skickar data till cachelagringen på begäran.This strategy loads data into the cache on demand. Bilden illustrerar hur du använder Cache-Aside-mönstret för att lagra data i cachelagringen.The figure illustrates using the Cache-Aside pattern to store data in the cache.

Använda Cache-Aside-mönstret för att lagra data i cachelagringen

Om ett program uppdaterar information kan det följa en strategi för genomskrivning genom att modifiera datalagringen och ogiltigförklara motsvarande objekt i cachen.If an application updates information, it can follow the write-through strategy by making the modification to the data store, and by invalidating the corresponding item in the cache.

Om ett objekt är det nästa att begäras kommer uppdaterade data att hämtas från datalagret och föras tillbaka till cachelagringen om du använder cache-aside-strategin.When the item is next required, using the cache-aside strategy will cause the updated data to be retrieved from the data store and added back into the cache.

Problem och övervägandenIssues and considerations

Tänk på följande när du bestämmer hur du ska implementera mönstret:Consider the following points when deciding how to implement this pattern:

Livslängd för cachelagrade data.Lifetime of cached data. Många cachen implementerar en förfalloprincip som upphäver data och tar bort dem från cachen om de inte använts under en viss period.Many caches implement an expiration policy that invalidates data and removes it from the cache if it's not accessed for a specified period. För att cache-aside ska vara effektivt säkerställer du att förfallopolicyn matchar mönstret för åtkomst till program som använder dessa data.For cache-aside to be effective, ensure that the expiration policy matches the pattern of access for applications that use the data. Gör inte förfalloperioden för kort, då det kan leda till att programmen hämtar data regelbundet från datalagret och lägger till dem i cachen.Don't make the expiration period too short because this can cause applications to continually retrieve data from the data store and add it to the cache. Gör inte heller förfalloperioden för lång, så att de cachelagrade datan med största säkerhet blir inaktuella.Similarly, don't make the expiration period so long that the cached data is likely to become stale. Kom ihåg att cachelagring är mest effektivt för relativt statiska data eller data som läses ofta.Remember that caching is most effective for relatively static data, or data that is read frequently.

Ta bort data.Evicting data. De flesta cacheminnen har en begränsad storlek jämfört med datalagret där informationen har sitt ursprung och de tar bort data när det behövs.Most caches have a limited size compared to the data store where the data originates, and they'll evict data if necessary. De flesta cacheminnen väljer vilka objekt som ska tas bort efter en princip om senast använda, men det kan anpassas.Most caches adopt a least-recently-used policy for selecting items to evict, but this might be customizable. Säkerställ att cachen är kostnadseffektiv genom att konfigurera den globala förfalloegenskapen och andra egenskaper för cachen samt förfalloegenskapen för varje cacheobjekt.Configure the global expiration property and other properties of the cache, and the expiration property of each cached item, to ensure that the cache is cost effective. Det är inte alltid lämpligt att tillämpa en global förfallopolicy till varje objekt i cachen.It isn't always appropriate to apply a global eviction policy to every item in the cache. Om ett cacheobjekt till exempel är väldigt dyrt att hämta från datalagret kan det vara fördelaktigt att behålla objektet i cachen på bekostnad av mer frekvent använda, men billigare objekt.For example, if a cached item is very expensive to retrieve from the data store, it can be beneficial to keep this item in the cache at the expense of more frequently accessed but less costly items.

Prima cachen.Priming the cache. Många lösningar fyller i cachen i förväg med data som ett program förmodligen kommer att behöva som en del av startup-processen.Many solutions prepopulate the cache with the data that an application is likely to need as part of the startup processing. Cache-Aside-mönstret kan fortfarande vara användbart om dessa data utgår eller avlägsnas.The Cache-Aside pattern can still be useful if some of this data expires or is evicted.

Konsekvens.Consistency. Konsekvens mellan datalagret och cachen garanteras inte av att Cache-Aside-mönstret implementeras.Implementing the Cache-Aside pattern doesn't guarantee consistency between the data store and the cache. Ett objekt i datalagret kan när som helst ändras av en extern process och ändringen kanske inte reflekteras i cachen förrän nästa gång objektet laddas.An item in the data store can be changed at any time by an external process, and this change might not be reflected in the cache until the next time the item is loaded. I ett system som replikerar data mellan datalager kan det här problemet bli allvarligt om synkronisering uppstår regelbundet.In a system that replicates data across data stores, this problem can become serious if synchronization occurs frequently.

Lokal (minnesintern) cachelagring.Local (in-memory) caching. Cachelagring kan vara lokalt i en programinstans och lagras internt.A cache could be local to an application instance and stored in-memory. Cache-aside kan vara användbart i den här miljön om ett program upprepade gånger använder samma data.Cache-aside can be useful in this environment if an application repeatedly accesses the same data. Däremot är lokala cache privata och anda programinstanser kan ha en kopia vardera av samma cachelagrade data.However, a local cache is private and so different application instances could each have a copy of the same cached data. Dessa data kan snabbt bli inkonsekventa mellan cachen, så det kan vara nödvändigt att ta bort data som lagras i privat cache och uppdatera oftare.This data could quickly become inconsistent between caches, so it might be necessary to expire data held in a private cache and refresh it more frequently. I de här scenariona bör du överväga att undersöka användningen av en delad eller distribuerad cachelagringsmekanism.In these scenarios, consider investigating the use of a shared or a distributed caching mechanism.

När du ska använda det här mönstretWhen to use this pattern

Använd det här mönstret i sådana här scenarier:Use this pattern when:

  • En cache tillhandahåller inte åtgärden för inbyggd genomläsning och -skrivning.A cache doesn't provide native read-through and write-through operations.
  • Resursbehovet är oförutsägbart.Resource demand is unpredictable. Det här mönstret gör det möjligt för program att läsa in data på begäran.This pattern enables applications to load data on demand. Det görs inga antaganden i förväg om vilka data som ett program kräver.It makes no assumptions about which data an application will require in advance.

Det här mönstret är kanske inte lämpligt om:This pattern might not be suitable:

  • När cachelagrade data är statiska.When the cached data set is static. Om dina data passar in i tillgängligt cacheutrymme ska du prima cachen med dina startup-data och tillämpa en policy som hindrar informationen från att upphöra att gälla.If the data will fit into the available cache space, prime the cache with the data on startup and apply a policy that prevents the data from expiring.
  • För tillståndsinformation om en cachelagringssession i ett webbprogram med en webbservergrupp som värd.For caching session state information in a web application hosted in a web farm. I den här miljön bör du undvika att introducera beroenden som baseras på tillhörighet mellan klient och server.In this environment, you should avoid introducing dependencies based on client-server affinity.

ExempelExample

I Microsoft Azure kan du använda Azure cache för Redis för att skapa en distribuerad cache som kan delas av flera instanser av ett program.In Microsoft Azure you can use Azure Cache for Redis to create a distributed cache that can be shared by multiple instances of an application.

I följande kod exempel används stackexchange. Redis -klienten, som är ett Redis-klient bibliotek som är skrivet för .net.This following code examples use the StackExchange.Redis client, which is a Redis client library written for .NET. Om du vill ansluta till en Azure-cache för Redis-instansen anropar du den statiska ConnectionMultiplexer.Connect metoden och skickar anslutnings strängen.To connect to an Azure Cache for Redis instance, call the static ConnectionMultiplexer.Connect method and pass in the connection string. Metoden returnerar ConnectionMultiplexer som representerar anslutningen.The method returns a ConnectionMultiplexer that represents the connection. En metod för att dela en ConnectionMultiplexer-instans i ditt program är att ha en statisk egenskap som returnerar en ansluten instans, ungefär som i följande exempel.One approach to sharing a ConnectionMultiplexer instance in your application is to have a static property that returns a connected instance, similar to the following example. Det här tillvägagångssättet är ett trådsäkert sätt för att endast initiera en enskild ansluten instans.This approach provides a thread-safe way to initialize only a single connected instance.

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;

GetMyEntityAsyncMetoden i följande kod exempel visar en implementering av Cache-Aside mönstret.The GetMyEntityAsync method in the following code example shows an implementation of the Cache-Aside pattern. Med den här metoden hämtas ett objekt från cachen med hjälp av metoden Read-through.This method retrieves an object from the cache using the read-through approach.

Ett objekt identifieras med hjälp av ett heltals-ID som nyckel.An object is identified by using an integer ID as the key. Metoden GetMyEntityAsync försöker hämta ett objekt med den här nyckeln från cachen.The GetMyEntityAsync method tries to retrieve an item with this key from the cache. Om ett matchande objekt hittas har det returnerats.If a matching item is found, it's returned. Om det inte finns någon matchning i cachen hämtar metoden GetMyEntityAsync objektet från ett datalager, lägger till det i cachen och returnerar det sedan.If there's no match in the cache, the GetMyEntityAsync method retrieves the object from a data store, adds it to the cache, and then returns it. Koden som faktiskt läser data från datalagringen visas inte här, eftersom den är beroende av datalagringen.The code that actually reads the data from the data store is not shown here, because it depends on the data store. Observera att det cachelagrade objektet är konfigurerat till att förfalla, så att det inte blir inaktuellt om det uppdateras på en annan plats.Note that the cached item is configured to expire to prevent it from becoming stale if it's updated elsewhere.

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

I exemplen används Azure cache för Redis för att komma åt butiken och hämta information från cachen.The examples use Azure Cache for Redis to access the store and retrieve information from the cache. Mer information finns i använda Azure cache för Redis och skapa en webbapp med Azure cache för Redis.For more information, see Using Azure Cache for Redis and How to create a Web App with Azure Cache for Redis.

Metoden UpdateEntityAsync nedan visar hur du upphäver ett objekt i cachen när värdet ändras av programmet.The UpdateEntityAsync method shown below demonstrates how to invalidate an object in the cache when the value is changed by the application. Koden uppdaterar den ursprungliga datalagringen och tar sedan bort det cachelagrade objektet från cacheminnet.The code updates the original data store and then removes the cached item from the 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.
}

Anteckning

Stegens ordning är viktig.The order of the steps is important. Uppdatera datalagringen innan du tar bort objektet från cachen.Update the data store before removing the item from the cache. Om du först tar bort det cachelagrade objektet finns en liten tidsram när en klient kan hämta objektet innan datalagret uppdateras.If you remove the cached item first, there is a small window of time when a client might fetch the item before the data store is updated. Det leder till en cachemiss (eftersom objektet togs bort från cachen) och gör så att en tidigare objektversion hämtas från datalagringen och förs tillbaka till cachen.That will result in a cache miss (because the item was removed from the cache), causing the earlier version of the item to be fetched from the data store and added back into the cache. Resultatet gör cachelagrade data inaktuella.The result will be stale cache data.

Följande information kan vara relevant när du implementerar det här mönstret:The following information may be relevant when implementing this pattern:

  • Vägledning för cachelagring.Caching Guidance. Tillhandahåller ytterligare information om hur du kan cachelagra data i en molnlösning och de problem som du bör ha i åtanke när du implementerar en cache.Provides additional information on how you can cache data in a cloud solution, and the issues that you should consider when you implement a cache.

  • Introduktion till data konsekvens.Data Consistency Primer. Molnprogram använder vanligtvis data som är utspridda över datalager.Cloud applications typically use data that's spread across data stores. Hantera och underhålla datakonsekvens i den här miljön är en viktig aspekt av systemet, särskilt problem som kan uppstå med samtidighet och tillgänglighet.Managing and maintaining data consistency in this environment is a critical aspect of the system, particularly the concurrency and availability issues that can arise. Primern beskriver problemet med konsekvens mellan distribuerade data och sammanfattar hur ett program kan implementera eventuell konsekvens för att upprätthålla datatillgänglighet.This primer describes issues about consistency across distributed data, and summarizes how an application can implement eventual consistency to maintain the availability of data.