分析一个错误使用MemoryCache导致的BUG

简介: 分析一个错误使用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内的元素输出出来,具体实现代码如下:

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

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

image.png

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

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();
}

修改后的输出结果如下:

image.png

总结:

MemoryCache背后其实就是ConcurrentDictionary,value其实是带着过期时间的CacheEntry,因此

在不过期并且没有发生变化的时候每次返回都是同一个缓存对象。作为缓存对象应进行只读操作,不应修改缓存对象,如需要修改应创建新对象而不是使用原来的对象。


目录
相关文章
|
6月前
|
测试技术
无法复现的bug,如何处理?
无法复现的bug,如何处理?
442 0
|
6月前
|
测试技术 API
修改bug引入更多bug怎么办?
修改bug引入更多bug怎么办?
122 0
|
6月前
|
前端开发
修正一些formdesigner的一些bug与操作
修正一些formdesigner的一些bug与操作
49 1
|
4月前
|
存储 数据库
cannot read properties of underfined (reading ‘code‘),别光知道抄,有的时候,细节就是影响全局关键,别人代码到你项目不一定100%正确,判断bug出
cannot read properties of underfined (reading ‘code‘),别光知道抄,有的时候,细节就是影响全局关键,别人代码到你项目不一定100%正确,判断bug出
|
6月前
|
测试技术
如何高质量的做BUG分析
如何高质量的做BUG分析
208 0
|
安全 编译器 Go
读<一例 Go 编译器代码优化 bug 定位和修复解析>
读<一例 Go 编译器代码优化 bug 定位和修复解析>
104 0
Drools 6.4.0Final版本KieScanner内存泄漏Bug
Drools 6.4.0Final版本KieScanner内存泄漏Bug
332 0
Drools 6.4.0Final版本KieScanner内存泄漏Bug
|
存储 监控
关于bug分析与异常处理的一些思考
我将bug依据复现的难易程度分为:必现的bug,比较容易复现的bug,很难复现的bug。 对于必现的bug,我通常淡定地称为其不是bug,因为,通过不断地复现,不断地调试,这些bug通常都能被解决,被解决了,还是bug么? 对于比较容易复现的bug,所谓比较容易复现,就是通过不太复杂操作,尝试几次、十几次,现象就可出现的bug,因为复现操作变得复杂,所以,为了每次复现能够获得更多的信息,尽量多地增加调试信息,以期望问题复现后,极大地缩小问题原因的范围。
1147 0
|
测试技术
BUG漏测的原因总结,以及如何处理
一、漏测的概率     漏测,是指软件产品的缺陷没有在测试过程中被发现,而是在版本发布之后,用户在使用过程中发现存在的缺陷。
2416 0
|
Web App开发 前端开发 JavaScript
前端特殊错误,Bug汇总
一直在做移动端的网页,遇到的各种问题感觉丝毫不下于PC端的各种浏览器兼容,这里总结一下,也是对自己的一个知识梳理 JavaScript UC白屏问题 错误表现:网页在微信和QQ内置浏览器访问正常,但是UC和大部分的手机自带浏览器访问页面会出现白屏,打印调试后发现,JS代码一句都没有执行。
1490 0