Gyorsítótár-feltöltési mintaCache-Aside pattern

Igény szerint tölthet be adatokat egy gyorsítótárba egy adattárolóból.Load data on demand into a cache from a data store. Ez javíthatja a teljesítményt, illetve segít a gyorsítótárban és a mögöttes adattárban tárolt adatok konzisztenciájának fenntartásában.This can improve performance and also helps to maintain consistency between data held in the cache and data in the underlying data store.

Kontextus és problémaContext and problem

Az alkalmazások gyorsítótár használatával javítják az adattárakban tárolt információkhoz való ismételt hozzáférést.Applications use a cache to improve repeated access to information held in a data store. Azt azonban nem célszerű feltételezni, hogy a gyorsítótárazott adatok mindig teljes mértékben konzisztensek az adattárban található adatokkal.However, it's impractical to expect that cached data will always be completely consistent with the data in the data store. Az alkalmazásokban olyan stratégiát érdemes megvalósítani, amely segít a lehető legnaprakészebb állapotban tartani a gyorsítótár adatait, de az olyan helyzeteket is tudja észlelni és kezelni, amikor a gyorsítótár adatai elavulttá váltak.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.

MegoldásSolution

Számos kereskedelmi gyorsítótárazási rendszer kínál visszaolvasási és visszaírási/háttérírási műveleteket.Many commercial caching systems provide read-through and write-through/write-behind operations. Ezekben a rendszerekben az alkalmazás a gyorsítótárra való hivatkozással kéri le az adatokat.In these systems, an application retrieves data by referencing the cache. Ha nincsenek a gyorsítótárban, az alkalmazás lekéri az adatokat az adattárból, majd hozzáadja őket a gyorsítótárhoz.If the data isn't in the cache, it's retrieved from the data store and added to the cache. A gyorsítótárban tárolt adatok módosításait a rendszer azonnal visszaírja az adattárba is.Any modifications to data held in the cache are automatically written back to the data store as well.

Az olyan gyorsítótárak esetében, amelyek nem biztosítják ezt a funkciót, a gyorsítótárat használó alkalmazásoknak kell karbantartaniuk az adatokat.For caches that don't provide this functionality, it's the responsibility of the applications that use the cache to maintain the data.

Az alkalmazások a gyorsítótár-feltöltő stratégiával emulálni tudják a visszaolvasási gyorsítótárazás funkciót.An application can emulate the functionality of read-through caching by implementing the cache-aside strategy. Ez a stratégia igény szerint tölti be az adatokat a gyorsítótárba.This strategy loads data into the cache on demand. Az ábrán látható, hogyan tárolhatók adatok a gyorsítótárban a gyorsítótár-feltöltési minta használatával.The figure illustrates using the Cache-Aside pattern to store data in the cache.

Adatok tárolása a gyorsítótárban a gyorsítótár-feltöltési minta használatával

Ha egy alkalmazás adatokat frissít, úgy követheti a visszaírási stratégiát, ha végrehajthatja a módosítást az adattárban, és érvényteleníti a megfelelő elemet a gyorsítótárban.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.

Amikor az elemre legközelebb szükség van, a gyorsítótár-feltöltő stratégia használatának köszönhetően az alkalmazás az adattárból kéri le a frissített adatokat, és újra hozzáadja őket a gyorsítótárhoz.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.

Problémák és megfontolandó szempontokIssues and considerations

A minta megvalósítása során az alábbi pontokat vegye figyelembe:Consider the following points when deciding how to implement this pattern:

A gyorsítótárazott adatok élettartama.Lifetime of cached data. Számos gyorsítótár használ elévülési szabályzatot, amely érvényteleníti és eltávolítja az adatokat a gyorsítótárból, ha adott ideig nem történik hozzáférés.Many caches implement an expiration policy that invalidates data and removes it from the cache if it's not accessed for a specified period. A hatékony gyorsítótár-felöltés érdekében győződjön meg arról, hogy az elévülési szabályzat megfelel az adatokat használó alkalmazások hozzáférési mintájának.For cache-aside to be effective, ensure that the expiration policy matches the pattern of access for applications that use the data. Ne szabja túl rövidre az elévülési időt, mert ez azt okozhatja, hogy az alkalmazások folyamatosan lekérik az adatokat az adattárból, és hozzáadják őket a gyorsítótárhoz.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. Az elévülési idő ne legyen olyan hosszú sem, hogy a gyorsítótárazott adatok elavuljanak.Similarly, don't make the expiration period so long that the cached data is likely to become stale. Vegye figyelembe, hogy a gyorsítótárazás a viszonylag statikus vagy gyakran beolvasott adatok esetében a leghatékonyabb.Remember that caching is most effective for relatively static data, or data that is read frequently.

Adatok kizárása.Evicting data. A legtöbb gyorsítótár mérete korlátozott azokhoz az adattárakhoz képest, ahonnan az adatok származnak, és szükség esetén kizárják az adatokat.Most caches have a limited size compared to the data store where the data originates, and they'll evict data if necessary. A legtöbb gyorsítótár a legrégebbi használat alapján választja ki a kizárandó elemeket, ez azonban testre szabható lehet.Most caches adopt a least-recently-used policy for selecting items to evict, but this might be customizable. Konfigurálja a globális lejárati tulajdonságot, a gyorsítótár egyéb tulajdonságait és az összes gyorsítótárazott elem lejáratát tulajdonságát úgy, hogy a gyorsítótár a lehető legköltséghatékonyabb legyen.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. Nem mindig jó megoldás, ha globális kizárási szabályzatot alkalmaz a gyorsítótár összes elemére.It isn't always appropriate to apply a global eviction policy to every item in the cache. Ha egy elemnek például rendkívül költséges az adattárból való lekérése, akkor előnyös lehet az elemet a gyorsítótárban tartani még a gyakrabban használt, de kevésbé költséges elemek rovására is.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.

A gyorsítótár előkészítése.Priming the cache. Számos megoldás előre feltölti a gyorsítótárat olyan adatokkal, amelyekre az alkalmazásnak valószínűleg szüksége lesz az első feldolgozás részeként.Many solutions prepopulate the cache with the data that an application is likely to need as part of the startup processing. A gyorsítótár-feltöltési minta az adatok egy részének elavulása vagy kizárása esetén is hasznos lehet.The Cache-Aside pattern can still be useful if some of this data expires or is evicted.

Konzisztencia.Consistency. A gyorsítótár-feltöltési minta megvalósítása nem garantálja az adattár és a gyorsítótár közötti konzisztenciát.Implementing the Cache-Aside pattern doesn't guarantee consistency between the data store and the cache. A külső folyamatok bármikor módosíthatják az adattár elemeit, és előfordulhat, hogy a gyorsítótár nem tükrözi ezeket a változásokat az elem következő betöltéséig.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. Olyan rendszer esetében, amely több adattárba replikál adatokat, ez komoly problémát jelenthet gyakori szinkronizálás esetén.In a system that replicates data across data stores, this problem can become serious if synchronization occurs frequently.

Helyi (memóriában történő) gyorsítótárazás.Local (in-memory) caching. Az alkalmazáspéldányok helyi gyorsítótárral is rendelkezhetnek, amelyet a memória tárol.A cache could be local to an application instance and stored in-memory. A gyorsítótár-feltöltés hasznos lehet az ilyen környezetben, ha az alkalmazás gyakran fér hozzá ugyanazon adatokhoz.Cache-aside can be useful in this environment if an application repeatedly accesses the same data. A helyi gyorsítótárak azonban magánjellegűek, ezért előfordulhat, hogy a különböző alkalmazáspéldányok mind rendelkeznek ugyanazon gyorsítótárazott adatok példányaival.However, a local cache is private and so different application instances could each have a copy of the same cached data. Ezek az adatok gyorsan inkonzisztenssé válhatnak a gyorsítótárak között, ezért szükség lehet a magánjellegű gyorsítótárak adatainak gyakoribb elévülésére és frissítésére.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. Ezekben az esetekben érdemes megfontolni egy megosztott vagy elosztott gyorsítótárazási mechanizmus használatát.In these scenarios, consider investigating the use of a shared or a distributed caching mechanism.

Mikor érdemes ezt a mintát használni?When to use this pattern

Használja ezt a mintát, ha:Use this pattern when:

  • A gyorsítótár nem biztosít natív visszaolvasási és visszaírási műveleteket.A cache doesn't provide native read-through and write-through operations.
  • Az erőforrásigény nem kiszámítható.Resource demand is unpredictable. Ez a minta lehetővé teszi az alkalmazások számára az adatok igény szerinti betöltését.This pattern enables applications to load data on demand. A minta nem feltételezi előzetesen, hogy az alkalmazásoknak milyen adatokra lesz szükségük.It makes no assumptions about which data an application will require in advance.

Nem érdemes ezt a mintát használni, ha:This pattern might not be suitable:

  • a gyorsítótárazott adatkészlet statikus.When the cached data set is static. Ha az adatok elférnek a rendelkezésre álló gyorsítótártérben, töltse fel a gyorsítótárat az adatokkal indításkor, és alkalmazzon egy szabályzatot, amely megakadályozza az adatok elévülését.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.
  • egy webfarmon üzemeltetett webalkalmazásban kíván munkamenet-állapotinformációkat gyorsítótárazni.For caching session state information in a web application hosted in a web farm. Ebben a környezetben érdemes elkerülnie az ügyfél–kiszolgáló affinitáson alapuló függőségek bevezetését.In this environment, you should avoid introducing dependencies based on client-server affinity.

PéldaExample

Microsoft Azure az Azure cache-t használhatja a Redis olyan elosztott gyorsítótár létrehozásához, amelyet egy alkalmazás több példánya is megoszthat.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.

A következő példák a StackExchange. Redis ügyfelet használják, amely a .net-hez írt Redis-ügyfél.This following code examples use the StackExchange.Redis client, which is a Redis client library written for .NET. Ha csatlakozni szeretne egy Azure-gyorsítótárhoz a Redis-példányhoz, hívja meg a statikus ConnectionMultiplexer.Connect metódust, és adja meg a kapcsolati karakterláncot.To connect to an Azure Cache for Redis instance, call the static ConnectionMultiplexer.Connect method and pass in the connection string. A metódus egy ConnectionMultiplexer értéket ad vissza, amely a kapcsolatot jelöli.The method returns a ConnectionMultiplexer that represents the connection. Az alkalmazásban egy ConnectionMultiplexer példány megosztására egy lehetséges módszer, ha létrehoz egy statikus tulajdonságot, amely egy csatlakoztatott példányt ad vissza, a következő példához hasonlóan.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. Ez a megközelítés egy szálbiztos módszert biztosít egyetlen csatlakoztatott példány inicializálásához.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;

A GetMyEntityAsync következő példában szereplő metódus a Cache-Aside minta megvalósítását mutatja be.The GetMyEntityAsync method in the following code example shows an implementation of the Cache-Aside pattern. Ezzel a módszerrel a rendszer lekérdezi az objektumot a gyorsítótárból az olvasási megközelítés használatával.This method retrieves an object from the cache using the read-through approach.

A metódus egy egész számból álló azonosítót használ kulcsként az objektumok azonosításához.An object is identified by using an integer ID as the key. A GetMyEntityAsync metódus megkísérel lekérdezni egy elemet a gyorsítótárból ezzel a kulccsal.The GetMyEntityAsync method tries to retrieve an item with this key from the cache. Ha a metódus talál egyező elemet, akkor visszaadja.If a matching item is found, it's returned. Ha nincs egyezés a gyorsítótárban, a GetMyEntityAsync metódus lekérdezi az objektumot az adattárból, hozzáadja a gyorsítótárhoz, majd visszaadja.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. Az adatokat az adattárból ténylegesen beolvasó kód itt nem látható, mert az az adattártól függően változhat.The code that actually reads the data from the data store is not shown here, because it depends on the data store. Figyelje meg, hogy a gyorsítótárazott elem úgy van konfigurálva, hogy elévüljön, és ne váljon elavulttá, ha máshol frissítik.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;
}

A példák az Azure cache-t használják a Redis az áruház eléréséhez és az információk lekéréséhez a gyorsítótárból.The examples use Azure Cache for Redis to access the store and retrieve information from the cache. További információ: az Azure cache használata a Redis és a webalkalmazások létrehozása az Azure cachehasználatával a Redis.For more information, see Using Azure Cache for Redis and How to create a Web App with Azure Cache for Redis.

Az alább látható UpdateEntityAsync metódus azt mutatja be, hogyan érvényteleníthető egy objektum a gyorsítótárban, ha egy alkalmazás módosítja az értékét.The UpdateEntityAsync method shown below demonstrates how to invalidate an object in the cache when the value is changed by the application. A kód frissíti az eredeti adattárat, majd eltávolítja a gyorsítótárazott elemet a gyorsítótárból.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.
}

Megjegyzés

A lépések sorrendje rendkívül fontos.The order of the steps is important. Frissítse az adattárat, mielőtt eltávolítaná az elemet a gyorsítótárból.Update the data store before removing the item from the cache. Ha először eltávolítja a gyorsítótárazott elemet, akkor az ügyfélnek csak rövid ideje lesz az elem lekérésére az adattár frissítése előtt.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. Emiatt a gyorsítótárból nem lesz találat (mivel az elemet eltávolították a gyorsítótárból), így a rendszer az elem egy korábbi változatát kéri le az adattárból és adja hozzá újra a gyorsítótárhoz.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. Ez pedig elavult gyorsítótár-adatokat eredményez.The result will be stale cache data.

Az alábbi információk segíthetnek a minta megvalósításakor:The following information may be relevant when implementing this pattern:

  • Gyorsítótárazási útmutató.Caching Guidance. További információkat biztosít arról, hogyan gyorsítótárazhat adatokat a felhőalapú megoldásokban, valamint a gyorsítótárak kialakítása előtt megfontolandó szempontokról.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.

  • Adatkonzisztencia– ismertető.Data Consistency Primer. A felhőalapú alkalmazások általában több adattárból származó adatokat használnak.Cloud applications typically use data that's spread across data stores. Az adatkonzisztencia felügyelete és fenntartása ebben a környezetben a rendszer kritikus fontosságú tényezője, különösen az egyidejűségi és rendelkezésre állási problémák miatt.Managing and maintaining data consistency in this environment is a critical aspect of the system, particularly the concurrency and availability issues that can arise. Ez az ismertető az elosztott adatok esetében felmerülő konzisztenciaproblémákat mutatja be, és összefoglalja, hogyan biztosíthatják az alkalmazások az adatok rendelkezésre állását a végleges konzisztencia megvalósításával.This primer describes issues about consistency across distributed data, and summarizes how an application can implement eventual consistency to maintain the availability of data.