背景

前些天公司服务器数据库访问量偏高,运维人员收到告警推送,安排我团队小伙伴排查原因.

我们发现原来系统定期会跑一个回归测试,该测运行的任务较多,每处理一条任务都会到数据库中取相关数据,高速地回归测试也带来了高频率的数据库读取.

解决方案1

我们认为每个任务要取的数据大相径庭,因此我们考虑对这个过程进行修改,加入MemoryCache把数据库中读取到的数据进行缓存.

整个修改非常简单,相信对常年混迹在博客园中的各位大佬来说小菜一碟,因此小弟不再叙述添加缓存的步骤细节.

从缓存的添加,代码提交,Teamcity 编译通过,到测试环境,QA环境的安装无比流畅,一切显得如手到擒来.

嗯,优秀是一种习惯, 没有一点办法.

人生如戏,当我们还沉浸在"我加的Cache不可能又BUG"的自信中时,QA传来噩耗,回归测试大量未通过 ....

故障排查

之前习惯了使用Redis缓存,因此,常识告诉我们 ---  在数据库中数据没有改动的前提下,加了缓存后读取的数据的效果和从数据库中读取的效果是一模一样的.

除非  ,,,   除非  这个常识是错误的....

因此我们加了日志,对写入缓存前后读取出来的数据进行了对比,结果出人意料.

该死 MemoryCache 毁我老脸,丢我精度,拿命来!!!!!

从日志中看到,第一行是从数据库中读取的结果,第二行是从cache中读取的,前两条数据完全一致,到了第三条,第四条,第五条,仔细观察发现,在小数点后面,居然有些小数点后比较微小的变化,不管变化的大小但数据确实发生改变了,所以MemoryCache会影响数据精度??这样会改变数据精度的MemoryCache又有何用??

机智的我,似乎早已看穿了一切,这肯定不是MenoryCache的锅!!!

不一样的MemoryCache

我从https://referencesource.microsoft.com 中扒出了MemoryCache的源码一探究竟.

定位到MemoryCache中的AddOrGetExisting方法,我们看到,其实我们把数据存储到该缓存的过程本质是把该对象存到一个名为_entries的         Hashtable 中,同样,取数据也是通过Key到该Hashtable中取出来,整个过程并没有对该对象进行序列化反序列等,也没有对该对象进行clone操作.这就意味着我们之前存入的,和后面取出的(不管我们从MemoryCache中取数据取多少次),永远只取出同一个对象.

这一点,和我之前使用的RedisCache是有很大区别的.我们在Redis中存入数据,是把对象序列化后存到Redis中,取数据是把Redis中的字节数据反序列成对象,意味着前一次存入的,和后一次取出的,已经不是同一个对象了,因此Redis中的数据是安全的.

猜想

我做出了一个大胆的猜想,之前从MemoryCache中取出来的数据之所以变化了,可能是取出对象后,复杂的处理过程中对该对象进行了什么修改操作,所以后期,再次从数据库中读取数据,读出来的已经已经不是最初存入的数据,而是前一次修改之后的数据.带着这个猜想,我对代码进行了修改.

解决方案2

从MenoryCache中取到数据后对结果进行clone(),这样即使程序对取出来的结果进行了修改也不会影响Cache中的数据了.

又是一次提心掉到的提交,编译,安装后, 回归测试顺利通过.

感觉人生到达了高潮   -_-

把踩得坑分享出来,希望后面的小伙伴引以为鉴,

原文地址:https://www.cnblogs.com/CoderAyu/p/10242230.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

C# Memory Cache 踩坑记录相关推荐

  1. mybatis学习与踩坑记录

    mybatis resultmap高级映射 应用场景:如果sql查询的列名和pojo的属性名不一致,可以使用resultMap将列名和pojo的属性名作一个对应关系,就可以映射成功了.(如果返回值为i ...

  2. Canal 及canal.admin(v1.1.5)踩坑记录

    网址:GitHub - alibaba/canal: 阿里巴巴 MySQL binlog 增量订阅&消费组件 前期软件准备 上面的软件包(canal.deployer-1.1.5.tar.gz ...

  3. Nvidia Jetson TX2 详细刷机教程及踩坑记录(Jetpack4.5.1,python3.6,torch1.6,torchvision0.7)

    最近接触到了Nvidia Jetson TX2这块开发板,想入手测试一下自己的深度学习模型,因此和TX2的故事开始了! 前言 本人刷机多次,尝试各种大小坑: 自带系统搭建环境:刚开始不想刷机,就自己手 ...

  4. 数据标注平台(CVAT)安装及踩坑记录

    目录 一.CVAT安装 step1 安装docker step2 获取权限 step3 获取权限 step4 克隆cvat源代码 step5 构建docker镜像 step6 运行Docker容器这一 ...

  5. ZED2代相机+nvidia jetson AGX xavier踩坑记录

    ZED2代相机+nvidia jetson AGX xavier踩坑记录 项目描述 nvidia jetson AGX xavier就不详细介绍了,jetson系列嵌入式开发板比一般的arrch64开 ...

  6. Java 线上惨痛踩坑记录,你也一定遇到过

    线上问题年年有,今年特别多.记几次线上惨痛的踩坑记录,希望大家以史为鉴. 1. 包装类型自动解箱导致空指针异常 public int getId() { Integer id = null; retu ...

  7. Java线上惨痛踩坑记录,你也一定遇到过

    线上问题年年有,今年特别多.记几次线上惨痛的踩坑记录,希望大家以史为鉴. 1. 包装类型自动解箱导致空指针异常 public int getId() {Integer id = null;return ...

  8. 为Jupyter notebook配置R kernel过程及踩坑记录

    为Jupyter notebook配置R kernel过程及踩坑记录 注意:本文为作者安装过程及折腾的过程,内容比较冗杂,如果读者想直接创建一个属于自己的子环境则参考: 如下文章: anaconda下 ...

  9. Python打包工具Pyintealler打包py文件为windows exe文件过程及踩坑记录+实战例子

    Python打包工具Pyintealler打包py文件为windows exe文件过程及踩坑记录+实战例子 目录 Python打包工具Pyintealler打包py文件为windows exe文件过程 ...

最新文章

  1. 厚积薄发!他读博前三年零文章,后期发力产出11篇一作,现任985高校博导
  2. Zabbix企业应用之服务器硬件信息监控
  3. 我们生活在一个虚拟世界的概率有多大?
  4. 一张图看懂微软人工智能
  5. 对南昌杀人案的一些看法
  6. JavaSE(二十四)——冒泡排序、选择排序、直接插入排序以及二分查找
  7. html画布 缩放的正方形,html5-canvas – 在动画HTML5画布中缩放和平移
  8. 一条命令教你安装centos下面的pip服务
  9. linux系统的运行级别
  10. javadoc 开源项目_在下一个项目中不使用JavaDoc的5大原因
  11. JavaWeb笔记:JDBC总结
  12. VBA SQL查询-记录集转数组
  13. 设置 mock_Quasar 使用 Mock.js
  14. Debian Linux下的Python学习——列表,元组和字典之列表
  15. 贵阳中职计算机学什么区别,贵阳中职计算机专业
  16. 「译」JavaScript 的 MVC 模式
  17. mysql的简单用法_mysql简单用法,以及增删改查语句
  18. Linux:使用libgen.h:basename,dirname
  19. C语言实现稳定的快排
  20. FTPClientUtil FTP客户端工具

热门文章

  1. 如何还原桌面图标_如何为Windows 10桌面图标还原或更改文本的默认外观?
  2. 用websploit获取管理员后台地址
  3. Photoshop脚本 使用ExtendScript编写Ps脚本
  4. Java读取word文件,字体,颜色
  5. 转: javascript技术栈
  6. python 3.* + Eclipse mar.2 +pydev 5.0 环境搭建
  7. ITU-R BT.656 协议
  8. 在ASP.Net Core和JAVA中,使用Azure配置密钥——Key Vault
  9. .NET 6 中 gRPC 的新功能
  10. .NET6 新功能和新生态