-
Notifications
You must be signed in to change notification settings - Fork 116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[QUESTION] Is it possible to have distinct objects for L1 and L2? #321
Comments
Uuh, this is an interesting challenge! |
@jodydonetti I have a related issue. The app memory is limited so typically one would not store everything in L1. Some things are meant to be stored only in L1 (e.g. memoization), some in L1 and L2 (very hot data) and some only in L2 as L2 has much larger memory to store data. For this, I have created multiple named caches, but the note on skipping memory caches which is a very common scenario is not encouraging:
#region add fusion cache
builder.Services.AddFusionCacheSystemTextJsonSerializer();
builder.Services.AddFusionCacheStackExchangeRedisBackplane(options =>
{
options.Configuration = builder.Configuration.Get<AppOptions>().Redis.Url;
options.ConfigurationOptions.ChannelPrefix = "fusion-cache-invalidation-channel";
});
// this named cache is used for memoization with no invalidation needed
builder.Services.AddFusionCache("MemoizationCache")
.WithDefaultEntryOptions(new FusionCacheEntryOptions
{
Duration = TimeSpan.FromDays(1),
JitterMaxDuration = TimeSpan.FromHours(10)
});
// this named cache is used for caching hot data in memory and distributed cache
builder.Services.AddFusionCache("HybridCache")
.WithDefaultEntryOptions(new FusionCacheEntryOptions
{
Duration = TimeSpan.FromDays(1),
JitterMaxDuration = TimeSpan.FromHours(1)
})
.WithRegisteredSerializer()
.WithRegisteredDistributedCache()
.WithRegisteredBackplane();
// this named cache is used for caching long lived data in distributed cache
builder.Services.AddFusionCache("DistributedCache")
.WithDefaultEntryOptions(new FusionCacheEntryOptions
{
Duration = TimeSpan.FromDays(1),
JitterMaxDuration = TimeSpan.FromHours(1),
SkipMemoryCacheRead = true,
SkipMemoryCacheWrite = true
})
.WithRegisteredSerializer()
.WithRegisteredDistributedCache();
#endregion |
Thanks for the input, appreciate it! Your setup then becomes like this: // this named cache is used for caching long lived data in distributed cache
builder.Services.AddFusionCache("DistributedCache")
.WithDefaultEntryOptions(new FusionCacheEntryOptions
{
Duration = TimeSpan.FromSeconds(1),
DistributedCacheDuration = TimeSpan.FromDays(1),
JitterMaxDuration = TimeSpan.FromHours(1)
})
.WithRegisteredSerializer()
.WithRegisteredDistributedCache(); Thoughts? |
Thanks for the quick reply. This gets me to another question, how often does fusion cache scan the memory cache to evict the expired items. Usually in other caching libs it is configurable and if it is not configurable what are the defaults used by fusion cache? |
Good question! I recently answered to exactly this recently here. Hope this helps, let me know. |
Thanks, this has been helpful! I still believe that storing non-hot data in the in-memory cache is an unnecessary use of resources. It increases the number of entries that the expiration scan needs to process, which can impact performance. Additionally, according to one of the references I came across, cache entries are not immediately removed from memory when they expire or are evicted from the cache—they are only cleared during the next garbage collection (GC) cycle. Under high load, this can lead to temporary memory spikes, which could have been avoided by solely relying on a distributed cache for non-hot data. |
One thing I'd like to understand is this: when you say "non-hot data" you still think that will be anyhow accessed, right?
Anyway, I would recap the 2 options as:
The nice thing is that you can pick the one you prefer (or try both and see how it goes) since they are both available. Hope this helps, let me know. |
Thanks for the comprehensive answer. I am now more inclined towards your suggestion |
Thanks for the insightful discussion! Using named caches might be a good idea. I'll leave this ticket open for now should anyone else have any suggestions. |
Thanks all, these discussions are really, really great. |
Hi, right now I am considering using FusionCache as an integration for an existing project, but have a bit of a challenge since it seems that the L1 and L2 caches have to be exactly the same.
A quick overview:
It looks like FusionCache only serializes what it has in L1 for L2 and no way to provide a distinction. Implementing my own
IFusionCacheSerializer
might work, but if I return the delegate only for L1, the serializer has no access to the string. I could try storing the string as a pair then see it in L2, but now I have a string and wasted memory since its only needed for the serializer.Why do this?
Your thoughts would be greatly appreciated!
The text was updated successfully, but these errors were encountered: