Opslaan in cache in .NET
In dit artikel krijgt u informatie over verschillende cachemechanismen. Caching is het opslaan van gegevens in een tussenliggende laag, waardoor volgende gegevens sneller worden opgehaald. Conceptueel is caching een strategie voor prestatieoptimalisatie en ontwerpoverwegingen. Caching kan de prestaties van apps aanzienlijk verbeteren door onregelmatig veranderende (of dure) gegevens beter beschikbaar te maken. In dit artikel worden de twee primaire typen caching geïntroduceerd en worden voorbeelden van broncode voor beide geboden:
Belangrijk
Er zijn twee MemoryCache
klassen in .NET, een in de System.Runtime.Caching
naamruimte en de andere in de Microsoft.Extensions.Caching
naamruimte:
Hoewel dit artikel is gericht op caching, bevat dit niet het System.Runtime.Caching
NuGet-pakket. Alle verwijzingen die moeten worden gebruikt MemoryCache
, bevinden zich in de Microsoft.Extensions.Caching
naamruimte.
Microsoft.Extensions.*
Alle pakketten zijn gereed voor afhankelijkheidsinjectie (DI), zowel de als IDistributedCache de IMemoryCache interfaces kunnen worden gebruikt als services.
In cachegeheugen opslaan
In deze sectie leert u meer over het pakket Microsoft.Extensions.Caching.Memory . De huidige implementatie van de app IMemoryCache is een wrapper rond de ConcurrentDictionary<TKey,TValue>, die een uitgebreide API beschikbaar maakt. Vermeldingen in de cache worden vertegenwoordigd door de ICacheEntryen kunnen elk object
zijn. De cacheoplossing in het geheugen is ideaal voor apps die op één server worden uitgevoerd, waarbij alle gegevens in de cache geheugen huren in het proces van de app.
Tip
Voor cachescenario's met meerdere servers kunt u overwegen om gedistribueerde caching te gebruiken als alternatief voor cacheopslag in het geheugen.
Cache-API in het geheugen
De consument van de cache heeft controle over zowel verschuivende als absolute vervaldatums:
- ICacheEntry.AbsoluteExpiration
- ICacheEntry.AbsoluteExpirationRelativeToNow
- ICacheEntry.SlidingExpiration
Als u een verlooptijd instelt, worden vermeldingen in de cache verwijderd als ze niet worden geopend binnen de vervaldatum. Consumenten hebben extra opties voor het beheren van cachevermeldingen via de MemoryCacheEntryOptions. Elk ICacheEntry is gekoppeld waarmee MemoryCacheEntryOptions de functionaliteit voor het verwijderen van vervaldatums beschikbaar wordt gemaakt met IChangeToken, prioriteitsinstellingen met CacheItemPriorityen het beheren van de ICacheEntry.Size. Houd rekening met de volgende uitbreidingsmethoden:
- MemoryCacheEntryExtensions.AddExpirationToken
- MemoryCacheEntryExtensions.RegisterPostEvictionCallback
- MemoryCacheEntryExtensions.SetSize
- MemoryCacheEntryExtensions.SetPriority
Voorbeeld van cache in het geheugen
Als u de standaard IMemoryCache implementatie wilt gebruiken, roept u de AddMemoryCache extensiemethode aan om alle vereiste services bij DI te registreren. In het volgende codevoorbeeld wordt de algemene host gebruikt om DI-functionaliteit beschikbaar te maken:
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();
Afhankelijk van uw .NET-workload hebt u mogelijk toegang tot de IMemoryCache
verschillende typen, zoals constructorinjectie. In dit voorbeeld gebruikt u het IServiceProvider
exemplaar op de host
algemene GetRequiredService<T>(IServiceProvider) extensiemethode en roept u deze aan:
IMemoryCache cache =
host.Services.GetRequiredService<IMemoryCache>();
Wanneer cacheservices in het geheugen zijn geregistreerd en opgelost via DI, kunt u beginnen met opslaan in de cache. In dit voorbeeld worden de letters in het Engelse alfabet 'A' tot en met Z herhaald. Het record AlphabetLetter
type bevat de verwijzing naar de brief en genereert een bericht.
file record AlphabetLetter(char Letter)
{
internal string Message =>
$"The '{Letter}' character is the {Letter - 64} letter in the English alphabet.";
}
Tip
De file
toegangsaanpassing wordt gebruikt voor het AlphabetLetter
type, omdat deze is gedefinieerd binnen en alleen toegankelijk is vanuit het Program.cs-bestand . Zie bestand (C#-verwijzing) voor meer informatie. Zie de sectie Program.cs voor meer informatie over de volledige broncode.
Het voorbeeld bevat een helperfunctie die door de alfabetletters wordt herhaald:
static async ValueTask IterateAlphabetAsync(
Func<char, Task> asyncFunc)
{
for (char letter = 'A'; letter <= 'Z'; ++letter)
{
await asyncFunc(letter);
}
Console.WriteLine();
}
In de voorgaande C#-code:
- De
Func<char, Task> asyncFunc
wordt op elke iteratie verwacht, waarbij de huidigeletter
wordt doorgegeven. - Nadat alle letters zijn verwerkt, wordt er een lege regel naar de console geschreven.
Als u items wilt toevoegen aan de cache, roept u een van de Create
, of Set
API's aan:
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;
In de voorgaande C#-code:
- De variabele
addLettersToCacheTask
delegeert naarIterateAlphabetAsync
en wordt verwacht. - Het
Func<char, Task> asyncFunc
wordt aangevoerd met een lambda. - De
MemoryCacheEntryOptions
instantie wordt geïnstantieerd met een absolute vervaldatum ten opzichte van nu. - Er wordt een terugbelaanroep na verwijdering geregistreerd.
- Een
AlphabetLetter
object wordt geïnstantieerd en doorgegeven Set aanletter
enoptions
. - De letter wordt naar de console geschreven omdat deze in de cache wordt opgeslagen.
- Ten slotte wordt er een Task.Delay geretourneerd.
Voor elke letter in het alfabet wordt een cachevermelding geschreven met een vervaldatum en wordt terugbellen na verwijdering geschreven.
De callback na verwijdering schrijft de details van de waarde die naar de console is verwijderd:
static void OnPostEviction(
object key, object? letter, EvictionReason reason, object? state)
{
if (letter is AlphabetLetter alphabetLetter)
{
Console.WriteLine($"{alphabetLetter.Letter} was evicted for {reason}.");
}
};
Nu de cache is gevuld, wordt er nog een aanroep IterateAlphabetAsync
verwacht, maar deze keer roept IMemoryCache.TryGetValueu het volgende aan:
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;
Als de cache
sleutel de letter
sleutel bevat en het value
een exemplaar is van een AlphabetLetter
sleutel die naar de console wordt geschreven. Wanneer de letter
sleutel zich niet in de cache bevindt, is deze verwijderd en is de callback na verwijdering aangeroepen.
Aanvullende uitbreidingsmethoden
De IMemoryCache
wordt geleverd met veel gemak gebaseerde uitbreidingsmethoden, waaronder een asynchrone GetOrCreateAsync
:
- CacheExtensions.Get
- CacheExtensions.GetOrCreate
- CacheExtensions.GetOrCreateAsync
- CacheExtensions.Set
- CacheExtensions.TryGetValue
Alles samenvoegen
De volledige broncode van de voorbeeld-app is een programma op het hoogste niveau en vereist twee NuGet-pakketten:
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.";
}
U kunt de MillisecondsDelayAfterAdd
en MillisecondsAbsoluteExpiration
waarden aanpassen om de wijzigingen in het gedrag van de vervaldatum en verwijdering van items in de cache te bekijken. Hier volgt voorbeelduitvoer van het uitvoeren van deze code. Vanwege de niet-deterministische aard van .NET-gebeurtenissen kan uw uitvoer afwijken.
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.
Omdat de absolute vervaldatum (MemoryCacheEntryOptions.AbsoluteExpirationRelativeToNow) is ingesteld, worden alle items in de cache uiteindelijk verwijderd.
Werkrolservice opslaan in cache
Een algemene strategie voor het opslaan van gegevens in de cache is het bijwerken van de cache onafhankelijk van de verbruikende gegevensservices. De worker-servicesjabloon is een goed voorbeeld, omdat de BackgroundService sjabloon onafhankelijk wordt uitgevoerd (of op de achtergrond) van de andere toepassingscode. Wanneer een toepassing wordt uitgevoerd die als host fungeert voor een implementatie van de IHostedServicetoepassing, wordt de bijbehorende implementatie (in dit geval de BackgroundService
of 'worker') in hetzelfde proces uitgevoerd. Deze gehoste services worden via de AddHostedService<THostedService>(IServiceCollection) extensiemethode geregistreerd bij DI als singletons. Andere services kunnen worden geregistreerd bij DI bij elke levensduur van de service.
Belangrijk
De levensduur van de service is erg belangrijk om te begrijpen. Wanneer u AddMemoryCache alle cacheservices in het geheugen registreert, worden de services geregistreerd als singletons.
Scenario fotoservice
Stel dat u een fotoservice ontwikkelt die afhankelijk is van API van derden die toegankelijk is via HTTP. Deze fotogegevens veranderen niet vaak, maar er is veel. Elke foto wordt vertegenwoordigd door een eenvoudig record
:
namespace CachingExamples.Memory;
public readonly record struct Photo(
int AlbumId,
int Id,
string Title,
string Url,
string ThumbnailUrl);
In het volgende voorbeeld ziet u dat er verschillende services worden geregistreerd bij DI. Elke service heeft één verantwoordelijkheid.
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();
In de voorgaande C#-code:
- De algemene host wordt gemaakt met standaardwaarden.
- Cacheservices in het geheugen worden geregistreerd bij AddMemoryCache.
- Een
HttpClient
exemplaar is geregistreerd voor deCacheWorker
klasse met AddHttpClient<TClient>(IServiceCollection). - De
CacheWorker
klasse is geregistreerd bij AddHostedService<THostedService>(IServiceCollection). - De
PhotoService
klasse is geregistreerd bij AddScoped<TService>(IServiceCollection). - De
CacheSignal<T>
klasse is geregistreerd bij AddSingleton. - De
host
app wordt geïnstantieerd vanuit de opbouwfunctie en is asynchroon gestart.
Het PhotoService
is verantwoordelijk voor het verkrijgen van foto's die voldoen aan bepaalde criteria (of 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();
}
}
}
In de voorgaande C#-code:
- De constructor vereist een
IMemoryCache
,CacheSignal<Photo>
enILogger
. - De
GetPhotosAsync
methode:- Definieert een
Func<Photo, bool> filter
parameter en retourneert eenIAsyncEnumerable<Photo>
. - Roept aan en wacht totdat de
_cacheSignal.WaitAsync()
release is uitgevoerd. Dit zorgt ervoor dat de cache wordt gevuld voordat de cache wordt geopend. - Oproepen
_cache.GetOrCreateAsync()
, asynchroon alle foto's in de cache krijgen. - Het
factory
argument registreert een waarschuwing en retourneert een lege fotomatrix. Dit zou nooit moeten gebeuren. - Elke foto in de cache wordt ge curseerd, gefilterd en gerealiseerd met
yield return
. - Ten slotte wordt het cachesignaal opnieuw ingesteld.
- Definieert een
Consumenten van deze service zijn gratis om methode aan te roepen GetPhotosAsync
en afhandelen foto's dienovereenkomstig. Er is geen HttpClient
vereiste omdat de cache de foto's bevat.
Het asynchrone signaal is gebaseerd op een ingekapseld SemaphoreSlim exemplaar binnen een beperkte singleton van een algemeen type. Het CacheSignal<T>
is afhankelijk van een instantie van 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();
}
In de voorgaande C#-code wordt het decoratorpatroon gebruikt om een exemplaar van de SemaphoreSlim
. Omdat het CacheSignal<T>
is geregistreerd als een singleton, kan deze worden gebruikt voor alle levensduur van de service met elk algemeen type, in dit geval de Photo
. Het is verantwoordelijk voor het signaleren van de seeding van de cache.
Het CacheWorker
is een subklasse van 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;
}
}
}
}
In de voorgaande C#-code:
- De constructor vereist een
ILogger
,HttpClient
enIMemoryCache
. - De
_updateInterval
is gedurende drie uur gedefinieerd. - De
ExecuteAsync
methode:- Lussen terwijl de app wordt uitgevoerd.
- Hiermee wordt een HTTP-aanvraag verzonden naar
"https://jsonplaceholder.typicode.com/photos"
en wordt het antwoord toegewezen als een matrix metPhoto
objecten. - De matrix met foto's wordt onder
IMemoryCache
de"Photos"
sleutel geplaatst. - Het
_cacheSignal.Release()
wordt aangeroepen, waarbij alle consumenten die op het signaal wachten, worden vrijgegeven. - De aanroep wordt Task.Delay in afwachting gegeven het update-interval.
- Na een vertraging van drie uur wordt de cache opnieuw bijgewerkt.
Consumenten in hetzelfde proces kunnen de IMemoryCache
foto's vragen, maar het is verantwoordelijk voor het CacheWorker
bijwerken van de cache.
Gedistribueerde caching
In sommige scenario's is een gedistribueerde cache vereist. Dit is het geval bij meerdere app-servers. Een gedistribueerde cache biedt ondersteuning voor een hogere uitschaling dan de in-memory caching-benadering. Als u een gedistribueerde cache gebruikt, wordt het cachegeheugen naar een extern proces verplaatst, maar vereist wel extra netwerk-I/O en introduceert u iets meer latentie (zelfs als nominaal).
De gedistribueerde cachingabstracties maken deel uit van het Microsoft.Extensions.Caching.Memory
NuGet-pakket en er is zelfs een AddDistributedMemoryCache
extensiemethode.
Let op
Het AddDistributedMemoryCache mag alleen worden gebruikt in ontwikkelings- en/of testscenario's en is geen haalbare productie-implementatie.
Bekijk een van de beschikbare implementaties van de IDistributedCache
volgende pakketten:
Microsoft.Extensions.Caching.SqlServer
Microsoft.Extensions.Caching.StackExchangeRedis
NCache.Microsoft.Extensions.Caching.OpenSource
Gedistribueerde cache-API
De gedistribueerde cache-API's zijn wat primitiever dan hun in-memory cache-API-tegenhangers. De sleutel-waardeparen zijn iets eenvoudiger. Cachesleutels in het geheugen zijn gebaseerd op een object
, terwijl de gedistribueerde sleutels een string
. Met in-memory caching kan de waarde elke sterk getypte algemene waarde zijn, terwijl waarden in gedistribueerde caching behouden blijven als byte[]
. Dat wil niet zeggen dat verschillende implementaties geen sterk getypte algemene waarden blootstellen, maar dat zou een implementatiedetails zijn.
Waarden maken
Als u waarden wilt maken in de gedistribueerde cache, roept u een van de set-API's aan:
Met behulp van de AlphabetLetter
record uit het cachevoorbeeld in het geheugen kunt u het object serialiseren naar JSON en vervolgens de string
coderen als: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);
Net als in-memory caching kunnen cachevermeldingen opties hebben om hun bestaan in de cache af te stemmen, in dit geval de DistributedCacheEntryOptions.
Extensiemethoden maken
Er zijn verschillende op gemak gebaseerde uitbreidingsmethoden voor het maken van waarden, die helpen bij het voorkomen van codering string
van weergaven van objecten in een byte[]
:
Waarden lezen
Als u waarden uit de gedistribueerde cache wilt lezen, roept u een van de get-API's aan:
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);
}
Zodra een cachevermelding uit de cache wordt gelezen, kunt u de UTF8-gecodeerde string
weergave ophalen uit de byte[]
Extensiemethoden lezen
Er zijn verschillende op het gemak gebaseerde uitbreidingsmethoden voor het lezen van waarden, die helpen bij het ontsleutelen byte[]
van de codering in string
weergaven van objecten:
Waarden bijwerken
Er is geen manier om de waarden in de gedistribueerde cache bij te werken met één API-aanroep. In plaats daarvan kunnen waarden hun schuifverlooptijd opnieuw instellen met een van de vernieuwings-API's:
Als de werkelijke waarde moet worden bijgewerkt, moet u de waarde verwijderen en deze vervolgens opnieuw toevoegen.
Waarden verwijderen
Als u waarden in de gedistribueerde cache wilt verwijderen, roept u een van de verwijder-API's aan:
Tip
Hoewel er synchrone versies van de bovengenoemde API's zijn, moet u rekening houden met het feit dat implementaties van gedistribueerde caches afhankelijk zijn van netwerk-I/O. Daarom heeft het de voorkeur meer dan niet om de asynchrone API's te gebruiken.