#yyds干货盘点#分析一个错误使用MemoryCache致使的BUG

2021年11月24日 阅读数:1
这篇文章主要向大家介绍#yyds干货盘点#分析一个错误使用MemoryCache致使的BUG,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

这个Bug是我在项目中发现的,缘由是MemoryCache使用不当形成了一个不小的Bug,虽然说这个Bug很大部分人都知道,可是我以为仍是分享出来,记录一下。废话很少说,咱们来看一下出错的代码(代码已经通过脱敏处理)缓存

await using var services =     new ServiceCollection()        .AddMemoryCache()        .BuildServiceProvider();GetValidValues(5).Dump();GetValidValues(8).Dump();List<int> GetValidValues(int valueInt){    var memoryCache = services.GetRequiredService<IMemoryCache>();    var vs= memoryCache.GetOrCreate("t1", entry =>    {        return Enumerable.Range(1, 10).ToList();    });    vs.RemoveAll(x => x > valueInt);    return vs;}

代码中Dump是扩展方法,它是把list内的元素输出出来,具体实现代码以下:ide

public static void Dump(this List<int> vs){    string v= string.Join("--", vs);    Console.WriteLine(v);}

好了,来想一下上面的输出结果会是什么吧,指望的结果应该是每次都输出小于等于输入的值,实际是什么样的呢?实际输出结果以下:ui

#yyds干货盘点#分析一个错误使用MemoryCache致使的BUG_扩展方法

从上图中第二次输出的结果是否是和你想的不同呢,之因此出现上面问题是由于MemoryCache对象是直接保存在内存中的,缓存不变化时每次都返回同一个对象,若是发生了修改那么再次获取就是修改后的内容。所以正确作法是返回一个新对象而不是修改原来的对象,一个修改方法以下:this

List<int> GetValidValues(int valueInt){    var memoryCache = services.GetRequiredService<IMemoryCache>();    var vs= memoryCache.GetOrCreate("t1", entry =>    {        return Enumerable.Range(1, 10).ToList();    });    return vs.Where(v => v <= valueInt).ToList();}

修改后的输出结果以下:spa

#yyds干货盘点#分析一个错误使用MemoryCache致使的BUG_ide_02

总结:code

MemoryCache背后其实就是ConcurrentDictionary,value实际上是带着过时时间的CacheEntry,所以在不过时而且没有发生变化的时候每次返回都是同一个缓存对象。做为缓存对象应进行只读操做,不该修改缓存对象,如须要修改应建立新对象而不是使用原来的对象。对象