【发布时间】:2018-07-27 20:27:48
【问题描述】:
我在 Asp.Net Core 中有一个项目。这个项目有一个 ICacheService 如下:
public interface ICacheService
{
T Get<T>(string key);
T Get<T>(string key, Func<T> getdata);
Task<T> Get<T>(string key, Func<Task<T>> getdata);
void AddOrUpdate(string key, object value);
}
实现只是基于ConcurrentDictionary<string, object>,所以它并不复杂,只是从这个字典存储和检索数据。在我的一项服务中,我有一种方法如下:
public async Task<List<LanguageInfoModel>> GetLanguagesAsync(string frontendId, string languageId, string accessId)
{
async Task<List<LanguageInfoModel>> GetLanguageInfoModel()
{
var data = await _commonServiceProxy.GetLanguages(frontendId, languageId, accessId);
return data;
}
_scheduler.ScheduleAsync($"{CacheKeys.Jobs.LanguagesJob}_{frontendId}_{languageId}_{accessId}", async () =>
{
_cacheService.AddOrUpdate($"{CacheKeys.Languages}_{frontendId}_{languageId}_{accessId}", await GetLanguageInfoModel());
return JobStatus.Success;
}, TimeSpan.FromMinutes(5.0));
return await _cacheService.Get($"{CacheKeys.Languages}_{frontendId}_{languageId}_{accessId}", async () => await GetLanguageInfoModel());
}
问题是我在这个方法中有三个参数用作缓存键。这很好用,但问题是三个参数的组合非常高,所以缓存中会有很多重复的对象。我正在考虑创建一个没有重复的缓存,如下所示:
拥有一个以列表为键的缓存,我可以为一个对象存储多个键。因此,当我获得新元素时,我将检查它们中的每一个是否在缓存中,如果它在缓存中,我只会在键列表中添加一个键,否则在缓存中插入一个新元素。这里的问题是测试一个对象是否在缓存中是一个大问题。我认为它会消耗大量资源,并且需要将一些序列化为特定形式以使比较成为可能,这将再次使比较消耗大量资源。
缓存可能看起来像这样 CustomDictionary<List<string>, object>
有没有人知道解决这个问题的好方法,不重复缓存中的对象?
编辑 1:
我主要担心的是当我从我的 web 服务中检索 List<MyModel> 时,因为它们可能有 80% 的对象具有相同的数据,这将大大增加内存的大小。但这也适用于简单的情况。
免得假设我有这样的事情:
MyClass o1 = new MyObject();
_cache.Set("key1", o1);
_cashe.Set("key2", o1);
在这种情况下,当尝试添加两次相同的对象时,我不想复制它,而是让key2 以某种方式指向与key1 相同的对象。如果实现了,那么使它们无效将是一个问题,但我希望有这样的东西:
_cache.Invalidate("key2");
这将检查是否有另一个键指向同一个对象。如果是这样,它只会删除密钥,否则会破坏对象本身。
【问题讨论】:
-
为什么不使用内置的内存缓存?
-
因为对我的需要 ConcurrentDictionary 已经足够了,另一个原因是因为我使用作业来更新它,据我所知,它对我来说是一个很好的解决方案。如果内置内存缓存对我的问题有一些优势,我会轻松切换到它
-
如果我理解正确,您只想在缓存中为
$"{CacheKeys.Languages}_{frontendId}_{languageId}_{accessId}"的所有组合存储一个对象,因此它们都具有相同的数据。那么为什么不直接使用 cons 字符串作为缓存呢?如果值相同,为什么它需要不同? -
你的意思是 GetLanguageInfoModel() for frontendid=1, languageid=2 and accessid=3 可以为三个参数的完全不同的值生成相同的模型?如果是这样,GetLanguageInfoModel() 与三个参数的关系如何?缓存键以独特的方式表示对象状态......可能键生成对于当前情况不是很正确?
-
@RajmondBurgaj 在 c# 中存储引用与在 c++ 中指向同一个对象完全相同。 .net 核心中的 IMemoryCache 可以满足您的所有需求。在存储时,您也可以存储现有对象的引用,IMemoryCache 可能只是错误地计算了它的内存占用,但您不会有重复的对象。当您为 key1 和 key2 存储 o1 时,谁告诉您它们是重复的?在这种情况下,它只是存储对原始 o1 的引用,而不是复制。
标签: c# caching asp.net-core