Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V tomto článku se dozvíte o různých mechanismech ukládání do mezipaměti. Ukládání dat do mezipaměti je ukládání dat v přechodné vrstvě, což zrychlová následné načítání dat. Konceptuálně je ukládání do mezipaměti strategií optimalizace výkonu a úvahou o návrhu. Ukládání do mezipaměti může výrazně zlepšit výkon aplikace tím, že data, která se mění jen zřídka nebo je nákladné je získat, zpřístupňuje snáze. Tento článek představuje dva primární typy ukládání do mezipaměti a poskytuje vzorový zdrojový kód pro oba:
Důležité
V rámci .NET existují dvě MemoryCache třídy, jedna v System.Runtime.Caching oboru názvů a druhá v Microsoft.Extensions.Caching oboru názvů:
I když se tento článek zaměřuje na ukládání do mezipaměti, neobsahuje System.Runtime.Caching balíček NuGet. Všechny odkazy na MemoryCache jsou v oboru názvů Microsoft.Extensions.Caching.
Microsoft.Extensions.* Všechny balíčky jsou připravené pro injektáž závislostí (DI), jak rozhraní IMemoryCache, tak rozhraní IDistributedCache lze použít jako služby.
Paměťová cache
V této části se dozvíte o balíčku Microsoft.Extensions.Caching.Memory . Aktuální implementace IMemoryCache je obálka zajišťující rozhraní API s bohatými funkcemi kolem ConcurrentDictionary<TKey,TValue>. Položky v mezipaměti jsou reprezentovány ICacheEntrya mohou být libovolné object. Řešení mezipaměti v paměti je skvělé pro aplikace, které běží na jednom serveru, kde všechna data uložená v mezipaměti využívají paměť v procesu aplikace.
Návod
U scénáře ukládání do mezipaměti s více servery zvažte použití přístupu distribuovaného ukládání do mezipaměti jako alternativu ke ukládání do mezipaměti v paměti.
Rozhraní API pro ukládání do mezipaměti v paměti
Uživatel mezipaměti má kontrolu nad posuvnou i absolutní dobou platnosti.
- ICacheEntry.AbsoluteExpiration
- ICacheEntry.AbsoluteExpirationRelativeToNow
- ICacheEntry.SlidingExpiration
Nastavení vypršení platnosti způsobí, že se položky v mezipaměti vyřadí , pokud nebudou v době vypršení platnosti přístupné. Spotřebitelé mají další možnosti pro řízení položek mezipaměti prostřednictvím MemoryCacheEntryOptions. Každý ICacheEntry je spárován s MemoryCacheEntryOptions tím, že zveřejňuje funkce vyřazení vypršení platnosti s IChangeToken, nastavení priority s CacheItemPrioritya řízení ICacheEntry.Size. Zvažte následující metody rozšíření:
- MemoryCacheEntryExtensions.AddExpirationToken
- MemoryCacheEntryExtensions.RegisterPostEvictionCallback
- MemoryCacheEntryExtensions.SetSize
- MemoryCacheEntryExtensions.SetPriority
Příklad mezipaměti v paměti
Chcete-li použít výchozí IMemoryCache implementaci, zavolejte metodu AddMemoryCache rozšíření pro registraci všech požadovaných služeb v DI. V následující ukázce kódu se obecný hostitel používá ke zveřejnění funkcí DI:
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMemoryCache();
using IHost host = builder.Build();
V závislosti na vaší úloze .NET můžete přistupovat k IMemoryCache různými způsoby, například pomocí injektování do konstruktoru. V této ukázce použijete instanci IServiceProvider na host a zavoláte obecnou rozšiřující metodu GetRequiredService<T>(IServiceProvider).
IMemoryCache cache =
host.Services.GetRequiredService<IMemoryCache>();
S zaregistrovanými službami ukládání do mezipaměti v paměti a vyřešenými prostřednictvím direktu můžete začít s ukládáním do mezipaměti. Tato ukázka prochází písmeny anglické abecedy od A do Z. Typ record AlphabetLetter obsahuje odkaz na písmeno a vygeneruje zprávu.
file record AlphabetLetter(char Letter)
{
internal string Message =>
$"The '{Letter}' character is the {Letter - 64} letter in the English alphabet.";
}
Návod
Modifikátor file přístupu se používá u AlphabetLetter typu, protože je definován v souboru Program.cs a je k němu přístup možný pouze z tohoto souboru. Další informace najdete v souboru (referenční dokumentace jazyka C#). Úplný zdrojový kód najdete v části Program.cs .
Ukázka obsahuje pomocnou funkci, která prochází písmeny abecedy:
static async ValueTask IterateAlphabetAsync(
Func<char, Task> asyncFunc)
{
for (char letter = 'A'; letter <= 'Z'; ++letter)
{
await asyncFunc(letter);
}
Console.WriteLine();
}
V předchozím kódu jazyka C#:
- Očekává se
Func<char, Task> asyncFuncpři každé iteraci a předává aktuálníletter. - Po zpracování všech písmen se do konzoly zapíše prázdný řádek.
Chcete-li přidat položky do mezipaměti, zavolejte jednu z API: Create nebo Set.
var addLettersToCacheTask = IterateAlphabetAsync(letter =>
{
MemoryCacheEntryOptions options = new()
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromMilliseconds(MillisecondsAbsoluteExpiration)
};
_ = options.RegisterPostEvictionCallback(OnPostEviction);
AlphabetLetter alphabetLetter =
cache.Set(
letter, new AlphabetLetter(letter), options);
Console.WriteLine($"{alphabetLetter.Letter} was cached.");
return Task.Delay(
TimeSpan.FromMilliseconds(MillisecondsDelayAfterAdd));
});
await addLettersToCacheTask;
V předchozím kódu jazyka C#:
- Proměnná
addLettersToCacheTaskdeleguje naIterateAlphabetAsynca je očekávána. - Diskutuje se o
Func<char, Task> asyncFunclambda. - Instance
MemoryCacheEntryOptionsje vytvořena s absolutním vypršením platnosti vzhledem k aktuálnímu okamžiku. - Zpětné volání po vyřazení je registrováno.
- Objekt
AlphabetLetterje instancován a předán do Set společně sletteraoptions. - Písmeno se zapíše do konzoly jako uložené v mezipaměti.
- Nakonec se vrátí Task.Delay.
Pro každé písmeno v abecedě se zapíše položka mezipaměti s vypršením platnosti a zpětné volání po vyřazení.
Zpětné volání po vyřazení zapíše podrobnosti o hodnotě, která byla vyřazena do konzoly:
static void OnPostEviction(
object key, object? letter, EvictionReason reason, object? state)
{
if (letter is AlphabetLetter alphabetLetter)
{
Console.WriteLine($"{alphabetLetter.Letter} was evicted for {reason}.");
}
};
Teď, když je mezipaměť naplněná, čeká se další volání IterateAlphabetAsync , ale tentokrát zavoláte IMemoryCache.TryGetValue:
var readLettersFromCacheTask = IterateAlphabetAsync(letter =>
{
if (cache.TryGetValue(letter, out object? value) &&
value is AlphabetLetter alphabetLetter)
{
Console.WriteLine($"{letter} is still in cache. {alphabetLetter.Message}");
}
return Task.CompletedTask;
});
await readLettersFromCacheTask;
Pokud cache obsahuje klíč letter a value je instancí AlphabetLetter, pak se to zapíše do konzoly.
letter Když klíč není v mezipaměti, byl vyřazen a poté bylo vyvoláno jeho zpětné volání po vyřazení.
Další metody rozšíření
IMemoryCache je dodáván s mnoha praktickými metodami rozšíření, včetně asynchronního GetOrCreateAsync.
- CacheExtensions.Get
- CacheExtensions.GetOrCreate
- CacheExtensions.GetOrCreateAsync
- CacheExtensions.Set
- CacheExtensions.TryGetValue
Dejte to všechno dohromady
Celý zdrojový kód ukázkové aplikace je program nejvyšší úrovně a vyžaduje dva balíčky NuGet:
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMemoryCache();
using IHost host = builder.Build();
IMemoryCache cache =
host.Services.GetRequiredService<IMemoryCache>();
const int MillisecondsDelayAfterAdd = 50;
const int MillisecondsAbsoluteExpiration = 750;
static void OnPostEviction(
object key, object? letter, EvictionReason reason, object? state)
{
if (letter is AlphabetLetter alphabetLetter)
{
Console.WriteLine($"{alphabetLetter.Letter} was evicted for {reason}.");
}
};
static async ValueTask IterateAlphabetAsync(
Func<char, Task> asyncFunc)
{
for (char letter = 'A'; letter <= 'Z'; ++letter)
{
await asyncFunc(letter);
}
Console.WriteLine();
}
var addLettersToCacheTask = IterateAlphabetAsync(letter =>
{
MemoryCacheEntryOptions options = new()
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromMilliseconds(MillisecondsAbsoluteExpiration)
};
_ = options.RegisterPostEvictionCallback(OnPostEviction);
AlphabetLetter alphabetLetter =
cache.Set(
letter, new AlphabetLetter(letter), options);
Console.WriteLine($"{alphabetLetter.Letter} was cached.");
return Task.Delay(
TimeSpan.FromMilliseconds(MillisecondsDelayAfterAdd));
});
await addLettersToCacheTask;
var readLettersFromCacheTask = IterateAlphabetAsync(letter =>
{
if (cache.TryGetValue(letter, out object? value) &&
value is AlphabetLetter alphabetLetter)
{
Console.WriteLine($"{letter} is still in cache. {alphabetLetter.Message}");
}
return Task.CompletedTask;
});
await readLettersFromCacheTask;
await host.RunAsync();
file record AlphabetLetter(char Letter)
{
internal string Message =>
$"The '{Letter}' character is the {Letter - 64} letter in the English alphabet.";
}
Klidně upravte hodnoty MillisecondsDelayAfterAdd a MillisecondsAbsoluteExpiration a sledujte změny v chování vypršení platnosti a vyřazení položek uložených v mezipaměti. Následuje ukázkový výstup spuštění tohoto kódu. Vzhledem k ne deterministické povaze událostí .NET se může výstup lišit.
A was cached.
B was cached.
C was cached.
D was cached.
E was cached.
F was cached.
G was cached.
H was cached.
I was cached.
J was cached.
K was cached.
L was cached.
M was cached.
N was cached.
O was cached.
P was cached.
Q was cached.
R was cached.
S was cached.
T was cached.
U was cached.
V was cached.
W was cached.
X was cached.
Y was cached.
Z was cached.
A was evicted for Expired.
C was evicted for Expired.
B was evicted for Expired.
E was evicted for Expired.
D was evicted for Expired.
F was evicted for Expired.
H was evicted for Expired.
K was evicted for Expired.
L was evicted for Expired.
J was evicted for Expired.
G was evicted for Expired.
M was evicted for Expired.
N was evicted for Expired.
I was evicted for Expired.
P was evicted for Expired.
R was evicted for Expired.
O was evicted for Expired.
Q was evicted for Expired.
S is still in cache. The 'S' character is the 19 letter in the English alphabet.
T is still in cache. The 'T' character is the 20 letter in the English alphabet.
U is still in cache. The 'U' character is the 21 letter in the English alphabet.
V is still in cache. The 'V' character is the 22 letter in the English alphabet.
W is still in cache. The 'W' character is the 23 letter in the English alphabet.
X is still in cache. The 'X' character is the 24 letter in the English alphabet.
Y is still in cache. The 'Y' character is the 25 letter in the English alphabet.
Z is still in cache. The 'Z' character is the 26 letter in the English alphabet.
Vzhledem k tomu, že je nastaveno absolutní vypršení platnosti (MemoryCacheEntryOptions.AbsoluteExpirationRelativeToNow), všechny položky uložené v mezipaměti se nakonec vyřadí.
Ukládání mezipaměti služby Worker
Jednou z běžných strategií ukládání dat do mezipaměti je aktualizace mezipaměti nezávisle na využívání datových služeb. Šablona Služby pracovního procesu je skvělým příkladem, protože BackgroundService běží nezávisle (nebo na pozadí) z jiného kódu aplikace. Když aplikace začne běžet a hostuje implementaci IHostedService, odpovídající implementace (v tomto případě BackgroundService neboli "pracovník") začne běžet ve stejném procesu. Tyto hostované služby jsou prostřednictvím metody rozšíření zaregistrované v DI jako singletony AddHostedService<THostedService>(IServiceCollection) . Ostatní služby je možné zaregistrovat v DI s libovolnou životností služeb.
Důležité
Životnost služby je velmi důležitá pro pochopení. Když voláte AddMemoryCache k registraci všech služeb ukládání do paměťové mezipaměti, jsou služby registrovány jako singletony.
Scénář fotoslužy
Představte si, že vyvíjíte fotoslužbě, která využívá rozhraní API třetích stran přístupné přes protokol HTTP. Tato data fotek se moc často nemění, ale je jich hodně. Každá fotografie je reprezentována jednoduchým record:
namespace CachingExamples.Memory;
public readonly record struct Photo(
int AlbumId,
int Id,
string Title,
string Url,
string ThumbnailUrl);
V následujícím příkladu uvidíte registraci několika služeb v DI. Každá služba má jednu zodpovědnost.
using CachingExamples.Memory;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddMemoryCache();
builder.Services.AddHttpClient<CacheWorker>();
builder.Services.AddHostedService<CacheWorker>();
builder.Services.AddScoped<PhotoService>();
builder.Services.AddSingleton(typeof(CacheSignal<>));
using IHost host = builder.Build();
await host.StartAsync();
V předchozím kódu jazyka C#:
- Obecný hostitel se vytvoří s výchozími nastaveními.
- Služby ukládání do paměti jsou registrovány v AddMemoryCache.
- Instance
HttpClientje zaregistrována pro tříduCacheWorkerprostřednictvím AddHttpClient<TClient>(IServiceCollection). - Třída
CacheWorkerje registrována u AddHostedService<THostedService>(IServiceCollection). - Třída
PhotoServiceje registrována u AddScoped<TService>(IServiceCollection). - Třída
CacheSignal<T>je registrována u AddSingleton. - Objekt
hostje vytvořen pomocí tvůrce a spuštěn asynchronně.
Zodpovídá PhotoService za získání fotek, které odpovídají zadaným kritériím (nebo filter):
using Microsoft.Extensions.Caching.Memory;
namespace CachingExamples.Memory;
public sealed class PhotoService(
IMemoryCache cache,
CacheSignal<Photo> cacheSignal,
ILogger<PhotoService> logger)
{
public async IAsyncEnumerable<Photo> GetPhotosAsync(Func<Photo, bool>? filter = default)
{
try
{
await cacheSignal.WaitAsync();
Photo[] photos =
(await cache.GetOrCreateAsync(
"Photos", _ =>
{
logger.LogWarning("This should never happen!");
return Task.FromResult(Array.Empty<Photo>());
}))!;
// If no filter is provided, use a pass-thru.
filter ??= _ => true;
foreach (Photo photo in photos)
{
if (!default(Photo).Equals(photo) && filter(photo))
{
yield return photo;
}
}
}
finally
{
cacheSignal.Release();
}
}
}
V předchozím kódu jazyka C#:
- Konstruktor vyžaduje
IMemoryCache,CacheSignal<Photo>aILogger. - Metoda
GetPhotosAsync:-
Func<Photo, bool> filterDefinuje parametr a vrátí hodnotuIAsyncEnumerable<Photo>. - Volání a čekání na uvolnění
_cacheSignal.WaitAsync()zajistí, že mezipaměť je naplněna dříve, než do ní přistoupíme. - Volá
_cache.GetOrCreateAsync(), asynchronně získává všechny fotky v mezipaměti. - Argument
factoryzaznamená upozornění a vrátí prázdné pole fotek . K tomu by nikdy nemělo dojít. - Každá fotografie v mezipaměti je iterována, filtrována a materializována pomocí
yield return. - Nakonec se signál mezipaměti resetuje.
-
Uživatelé této služby mohou volat metodu GetPhotosAsync a odpovídajícím způsobem zpracovávat fotografie. Není vyžadován HttpClient, protože mezipaměť obsahuje fotografie.
Asynchronní signál je založen na zapouzdřené SemaphoreSlim instanci v rámci omezeného singletonu obecného typu. Spoléhá CacheSignal<T> na instanci SemaphoreSlim:
namespace CachingExamples.Memory;
public sealed class CacheSignal<T>
{
private readonly SemaphoreSlim _semaphore = new(1, 1);
/// <summary>
/// Exposes a <see cref="Task"/> that represents the asynchronous wait operation.
/// When signaled (consumer calls <see cref="Release"/>), the
/// <see cref="Task.Status"/> is set as <see cref="TaskStatus.RanToCompletion"/>.
/// </summary>
public Task WaitAsync() => _semaphore.WaitAsync();
/// <summary>
/// Exposes the ability to signal the release of the <see cref="WaitAsync"/>'s operation.
/// Callers who were waiting, will be able to continue.
/// </summary>
public void Release() => _semaphore.Release();
}
V předchozím kódu jazyka C# se vzor dekorátoru používá k zabalení instance objektu SemaphoreSlim. Vzhledem k tomu, že je CacheSignal<T> zaregistrován jako singleton, lze ho použít napříč všemi životnostmi služeb s jakýmkoli obecným typem – v tomto případě Photo. Zodpovídá za signalizaci inicializace mezipaměti.
Jedná se CacheWorker o podtřídu BackgroundService:
using System.Net.Http.Json;
using Microsoft.Extensions.Caching.Memory;
namespace CachingExamples.Memory;
public sealed class CacheWorker(
ILogger<CacheWorker> logger,
HttpClient httpClient,
CacheSignal<Photo> cacheSignal,
IMemoryCache cache) : BackgroundService
{
private readonly TimeSpan _updateInterval = TimeSpan.FromHours(3);
private bool _isCacheInitialized = false;
private const string Url = "https://jsonplaceholder.typicode.com/photos";
public override async Task StartAsync(CancellationToken cancellationToken)
{
await cacheSignal.WaitAsync();
await base.StartAsync(cancellationToken);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
logger.LogInformation("Updating cache.");
try
{
Photo[]? photos =
await httpClient.GetFromJsonAsync<Photo[]>(
Url, stoppingToken);
if (photos is { Length: > 0 })
{
cache.Set("Photos", photos);
logger.LogInformation(
"Cache updated with {Count:#,#} photos.", photos.Length);
}
else
{
logger.LogWarning(
"Unable to fetch photos to update cache.");
}
}
finally
{
if (!_isCacheInitialized)
{
cacheSignal.Release();
_isCacheInitialized = true;
}
}
try
{
logger.LogInformation(
"Will attempt to update the cache in {Hours} hours from now.",
_updateInterval.Hours);
await Task.Delay(_updateInterval, stoppingToken);
}
catch (OperationCanceledException)
{
logger.LogWarning("Cancellation acknowledged: shutting down.");
break;
}
}
}
}
V předchozím kódu jazyka C#:
- Konstruktor vyžaduje
ILogger,HttpClientaIMemoryCache. -
_updateIntervalje definován na tři hodiny. - Metoda
ExecuteAsync:- Smyčky, když je aplikace spuštěná.
- Vytvoří požadavek HTTP na
"https://jsonplaceholder.typicode.com/photos"a mapuje odpověď jako polePhotoobjektů. - Pole fotek je umístěno do
IMemoryCachepod klíčem"Photos". - Je zavolán
_cacheSignal.Release(), čímž se uvolní všichni uživatelé, kteří čekali na tento signál. - Volání Task.Delay, které je očekáváno, je vzhledem k intervalu aktualizace.
- Po zpoždění po dobu tří hodin se mezipaměť znovu aktualizuje.
Uživatelé ve stejném procesu mohou požádat IMemoryCache o fotky, ale CacheWorker je zodpovědný za aktualizaci mezipaměti.
Distribuované ukládání do mezipaměti
V některých scénářích se vyžaduje distribuovaná mezipaměť – to je případ několika aplikačních serverů. Distribuovaná mezipaměť umožňuje vyšší škálovatelnost než ukládání do mezipaměti v paměti. Použití distribuované mezipaměti přesměruje paměť mezipaměti do externího procesu, ale vyžaduje další vstupně-výstupní operace sítě a zavádí trochu větší latenci (i když je nominální).
Distribuovaná Microsoft.Extensions.Caching.Memory abstrakce ukládání do mezipaměti jsou součástí balíčku NuGet a existuje dokonce i AddDistributedMemoryCache metoda rozšíření.
Upozornění
Měla AddDistributedMemoryCache by se používat pouze ve scénářích vývoje a/nebo testování a nejedná se o vhodnou produkční implementaci.
Vezměte v úvahu některou z dostupných implementací IDistributedCache následujících balíčků:
Microsoft.Extensions.Caching.SqlServerMicrosoft.Extensions.Caching.StackExchangeRedisNCache.Microsoft.Extensions.Caching.OpenSource
Distribuované rozhraní API pro ukládání do mezipaměti
Distribuovaná rozhraní API pro ukládání do mezipaměti jsou trochu primitivnější než jejich protějšky rozhraní API pro ukládání do mezipaměti v paměti. Páry klíč-hodnota jsou o něco jednodušší. Klíče pro ukládání do mezipaměti v paměti jsou založeny na object, zatímco distribuované klíče jsou string. Při ukládání do paměti může být hodnota jakýkoli silně typovaný generický typ, zatímco hodnoty v distribuované mezipaměti jsou trvalé jako byte[]. To neznamená, že různé implementace nezpřístupňují silně typované generické hodnoty, ale to je detail implementace.
Vytvoření hodnot
Pokud chcete vytvořit hodnoty v distribuované mezipaměti, zavolejte jedno z nastavených rozhraní API:
AlphabetLetter Pomocí záznamu z příkladu mezipaměti v paměti můžete objekt serializovat do formátu JSON a pak kódovat string jako byte[]:
DistributedCacheEntryOptions options = new()
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromMilliseconds(MillisecondsAbsoluteExpiration)
};
AlphabetLetter alphabetLetter = new(letter);
string json = JsonSerializer.Serialize(alphabetLetter);
byte[] bytes = Encoding.UTF8.GetBytes(json);
await cache.SetAsync(letter.ToString(), bytes, options);
Podobně jako u ukládání mezipaměti přímo v paměti mohou mít položky mezipaměti různé volby, které pomáhají doladit jejich existenci v mezipaměti – v tomto případě DistributedCacheEntryOptions.
Vytvoření rozšiřujících metod
Existuje několik metod rozšíření založených na pohodlí pro vytváření hodnot, které pomáhají vyhnout se kódování string reprezentací objektů do byte[]:
Čtení hodnot
Pokud chcete číst hodnoty z distribuované mezipaměti, zavolejte jedno z rozhraní API get:
AlphabetLetter? alphabetLetter = null;
byte[]? bytes = await cache.GetAsync(letter.ToString());
if (bytes is { Length: > 0 })
{
string json = Encoding.UTF8.GetString(bytes);
alphabetLetter = JsonSerializer.Deserialize<AlphabetLetter>(json);
}
Jakmile se položka mezipaměti přečte z mezipaměti, můžete získat reprezentaci zakódovanou string kódováním UTF8 z byte[]
Přečíst metody rozšíření
Existuje několik metod rozšíření založených na pohodlí pro čtení hodnot, které pomáhají vyhnout se dekódování byte[] do string reprezentace objektů:
Aktualizace hodnot
Neexistuje způsob, jak aktualizovat hodnoty v distribuované mezipaměti jedním voláním rozhraní API, místo toho můžou mít hodnoty resetování jejich posuvných vypršení platnosti pomocí některého z rozhraní API pro aktualizaci:
Pokud je potřeba aktualizovat skutečnou hodnotu, musíte tuto hodnotu odstranit a pak ji znovu přidat.
Odstranění hodnot
Pokud chcete odstranit hodnoty v distribuované mezipaměti, zavolejte jedno z rozhraní API pro odebrání:
Návod
I když existují synchronní verze výše uvedených rozhraní API, zvažte skutečnost, že implementace distribuovaných mezipamětí jsou závislé na vstupně-výstupních operacích sítě. Z tohoto důvodu se upřednostňují asynchronní rozhraní API.