alastairtree / LazyCache

An easy to use thread safe in-memory caching service with a simple developer friendly API for c#
https://nuget.org/packages/LazyCache
MIT License
1.72k stars 159 forks source link

Is there an easy and safe way to add cache per user? #77

Closed arisliang closed 4 years ago

arisliang commented 5 years ago

Usually cache is at global level, is there an easy and safe way to make it different for different user?

alastairtree commented 5 years ago

How about just putting the userid as part of the cache key?

arisliang commented 5 years ago

A bit hard wire, but it'll work.

How about some kind of built-in "scoping" mechanism? So it'll make sure different scope won't accidentally access other scope's data compared with hard wiring it. A bit like session, a built-in user specific space

alastairtree commented 4 years ago

There are some sensible performance reasons why usually you should only have a single cache - it makes it easier to manage size under memory pressure as only one cleanup is needed - and performance counters make more sense across all cache use and not just for one cache of many.

The best solution is probably just to use a userID prefix in the cache key which is how most "scoped caches" or "cache ranges" work.

However, you could hold multiple instances of the CachingService (each with their own CacheProvider/MemoryCache instance) and store them in a dictionary by UserId if you needed to and wanted them firmly segregated. This will be more of a roll-your-own solution and not something to be built into LazyCache at this time.

Hope that helps.

mkgn commented 2 years ago

@alastairtree , I have a similar requirement where each Tenant has some data that i need to cache separately. Currently I am using ConcurrentDictionaries. And to get it to work I do something like below;

cacheholder = new ConcurrentDictionary<tenant,ConcurrentDictionary<string,string>> <- for each tenant I have another concurrent dictionary storing that tenant's data. When reading/writing values it'll be like;

cacheholder[tenant_name].AddMyData(key,value) 

Now I need to move away from ConcurrentDictionary as I see some performance issues in future. So thought to give this library a try. Now in your case to do the same thing I guess I can do something like below;

cacheholder = new ConcurrentDictionary<tenant, new CacheingService()> 

I guess above approach would work right?

alastairtree commented 2 years ago

Looks fine to me. Would be tempted to use them IAppCache interface in the dictionary rather than caching service.