一:背景

1. 讲故事

18年的时候在做纯内存项目的过程中遇到了这么一个问题,因为一些核心数据都是飘在内存中,所以内存空间对我们来说额外宝贵,但偏偏项目中有些数据需要缓存,比如说需要下钻的报表上的点,基于性能的考虑,不希望采用独立的缓存中间件,比如 redis, mongodb,毕竟再怎么滴还是要走网络io,但直接放在本机内存中也不现实,那有没有均衡于 native cache 和 cache server 之间的方案呢?对的,就是 disk cache,毕竟 磁盘IO 的读写要远大于网络IO,更何况配的是 SSD 呢。

二:寻找解决方案

1. 检索 github

有了 disk cache 这个大方向就可以去 github 上检索关键词,看看有没有类似的中间件,说实话,java的倒不少,比如著名的 guava,ehcache,不仅有cache的简单操作,还附带各种统计信息,刷新了对缓存认知的三观哈,尤其是 ehcache 太????????了,堆内,堆外,磁盘,分布式通通支持,用 C# 写的好不容易找到一个 disk cache 还不幸是收费的,气人哈,用 C# 调用 Java 肯定不现实了哈。

2. 使用sqlite作为 disk cache

既然开源社区没什么好的东西,看来只能自己封装一下了,像 ehcache 那种高阶的 diskcache 搞不定,用简单的 sqlite 作为本机的 diskcahe 还是可以的,接下来试试看。

class DiskCache{private static readonly string dbFile = $@"{Environment.CurrentDirectory}\mysqlite1.db";private static readonly string connectionString = $@"Data Source={dbFile};Version=3";//过期数据监测:【一分钟来一次】private static Timer timer = new Timer((arg) =>{}, null, 1000, 1000 * 60);static DiskCache(){if (!File.Exists(dbFile)){var schema = @"CREATE TABLE Cache (cachekey   VARCHAR (1000) PRIMARY KEY  NOT NULL,cachevalue TEXT                        NOT NULL,created    DATE                        NOT NULL,expried    DATE                        NOT NULL);";using (SQLiteConnection connection = new SQLiteConnection(connectionString)){connection.Execute(schema);}}}public static void Set<T>(string key, T value, int expiredMinutes){using (SQLiteConnection connection = new SQLiteConnection(connectionString)){var sql = $"delete from Cache where cachekey =@key;" +$"insert into Cache(cachekey,cachevalue,created,expried) values (@cachekey,@cachevalue,@created,@expried)";connection.Execute(sql, new{key = key,cachekey = key,cachevalue = Newtonsoft.Json.JsonConvert.SerializeObject(value),created = DateTime.Now,expried = DateTime.Now.AddMinutes(expiredMinutes)});}}public static T Get<T>(string key){using (SQLiteConnection connection = new SQLiteConnection(connectionString)){var sql = $"select cachevalue from Cache where cachekey=@cachekey and expried > @expried";var query = connection.QueryFirstOrDefault(sql, new { cachekey = key, expried = DateTime.Now });var json = JsonConvert.DeserializeObject<T>(query.cachevalue);return json;}}}

这里有二个注意点:

  • 因为是做缓存,所以数据库和表的创建都要通过程序自动化,数据库是否存在判断 file 文件是否存在即可。

  • 过期数据的问题,因为我有 expried 字段,这一点可以学习GC思想,使用 Timer 在后台定期清理。

有了这些基础之后,原子化的缓存就实现好了,接下来试一下基本的 Get / Set 方法。

这个方案很好的节省了我宝贵的内存,同时速度又是 networkio 和 native 之间的一个平衡,算是个不错的解决办法吧。

三:aspnetcore 的 EasyCaching

EasyCaching 是园子里 @Catcher Wong 的作品 [https://www.cnblogs.com/catcher1994/p/10806607.html],点赞~~~ 看了下提供了很多种 provider,如下图:

我想后面肯定还会有更多的 provider 出现,如:leveldb,Cassandra,接下来看看这玩意怎么玩。

1. 安装使用

在 nuget 上 搜一下 EasyCaching.SQLite 安装即可,接下来就是使用文档:https://easycaching.readthedocs.io/en/latest/SQLite/#2-config-in-startup-class 如下图:

文档中是采用依赖注入的方式,而我的程序是 console 模式的后端服务,并没有 ServiceCollection,先模拟着试试看。

static void Main(string[] args){IServiceCollection services = new ServiceCollection();services.AddEasyCaching(option =>{option.UseSQLite(c =>{c.DBConfig = new SQLiteDBOptions{FileName = "demo.db",CacheMode = SqliteCacheMode.Default,OpenMode = SqliteOpenMode.ReadWriteCreate,};}, "m1");});IServiceProvider serviceProvider = services.BuildServiceProvider();var factory = serviceProvider.GetService<IEasyCachingProviderFactory>();var cache = factory.GetCachingProvider("m1");cache.Set("user", "hello world!", TimeSpan.FromSeconds(20));var info = cache.Get<string>("user");Console.WriteLine(info);}

接下来用 SQLiteStudio 打开 demo.db 看一下数据呈现,如下图:

可以看到人家的框架比我的多了一个 name 字段,看样子是给 多个 cache 做隔离用的,不过这里貌似有三个需要优化的地方。

  • 并不是每一个程序都要使用 依赖注入 的方式 ,提供更便捷的方式初始化就更好了。

  • 看了下源码,并没有找到可以定期删除过期数据的业务逻辑。

  • 建议提供一些 cache 的统计信息,如命中次数,某一个key最后命中时间等等时分统计图。

四:总结

可能很多人说都什么年代了还用 disk cache,这偏偏这万千世界啥需求都有,这几年开源项目越来越多,社区向好,值得点赞。

内存不够用还要速度快,终于找到可以基于 File 的 Cache 了相关推荐

  1. sqlite的速度_内存不够用还要速度快,终于找到可以基于 File 的 Cache 了

    (给DotNet加星标,提升.Net技能) 转自:一线码农cnblogs.com/huangxincheng/p/13548518.html 一.背景 1.讲故事 18年的时候在做纯内存项目的过程中遇 ...

  2. 试用了多款报表工具,终于找到了基于.Net 6开发的一个了

    Part1前言 上一个月有一个项目需要用到数据分析,将老板感兴趣的数据给他整理成一个面板,方便他实时查看,于是自己了解到了BI,当时我们项目就用了metabase,metabase是一款开源的BI分析 ...

  3. 安卓手机突然很卡_为什么你的安卓手机越用越卡,真是内存不够?终于找到原因了!...

    为什么你的安卓手机越用越卡,真是内存不够?终于找到原因了! 现在在手机市场里基本上是被两个系统瓜分了市场,一个是苹果手机的iOS系统,一个是国产手机的安卓系统.在以前很多用户会选择使用苹果手机,因为苹 ...

  4. 裸辞4个月,面试了34家公司,终于找到理想工作了

    上半年裁员,下半年裸辞,有不少人高呼裸辞后躺平真的好快乐!但也有很多人,裸辞后的生活五味杂陈. 面试34次终于找到心仪工作 因为工作压力大.领导PUA等各种原因,今年2月下旬我从一家互联网小厂裸辞,没 ...

  5. 裸辞4个月,面试了30家公司,终于找到理想工作了

    上半年裁员,下半年裸辞,有不少人高呼裸辞后躺平真的好快乐!但也有很多人,裸辞后的生活五味杂陈. 面试30次终于找到心仪工作 因为工作压力大.领导PUA等各种原因,今年2月下旬我从一家互联网小厂裸辞,没 ...

  6. 裸辞3个月,面试了25家公司,终于找到心仪的工作了

    ​上半年裁员,下半年裸辞,有不少人高呼裸辞后躺平真的好快乐!但也有很多人,裸辞后的生活五味杂陈. 面试25次终于找到心仪工作 因为工作压力大.领导PUA等各种原因,今年2月下旬我从一家互联网小厂裸辞, ...

  7. 电脑无法检查计算机更新,赶紧检测下!新买的电脑不能升级Win 11?问题终于找到了...

    原标题:赶紧检测下!新买的电脑不能升级Win 11?问题终于找到了 微软在6月24日晚11点,正式发布了Win 11系统,这是至2015年之后最大的一次Windows系统升级,不仅界面发生大变化,连功 ...

  8. emwin读取sd图片_手机内存不够用?这样清理垃圾文件和巧用SD卡扩容硬件存储空间...

    手机是我们离不开的电器,随着信息越来越多,各种app装的越来越多,有时候会提示存储空间已满,土豪还好,可以更换旗舰手机,可怜我们普通人,尤其是比较旧一些的手机,可用空间越来越小,不用担心,按照本文要说 ...

  9. 终于找到个好办法备份数据库了

    环境:web服务器和数据库服务器分离,数据库服务器不对外网开放. 数据库的user库共有6G大: 在线通过webshell连接到数据库服务器,用webshell自带功能备份其中的user库,备份的时候 ...

最新文章

  1. PRD 的编写和修改注意事项
  2. 云原生时代消息中间件的演进路线
  3. ASP.NET MVC SSO单点登录设计与实现
  4. 【电路补习笔记】5、三极管的参数与选型
  5. 前端学习(1748):前端调试值之console的一些设置
  6. access日期如何增加年数_如何为Access数据库表添加日期或时间戳
  7. 94年的博士后又拿到了这个金奖!原来是他的学弟
  8. 微软宣布 .NET 5 计划,支持跨平台、移动开发
  9. 计算机三级-数据库技术
  10. java 优酷视频缩略图_通过正则表达式获取优酷视频缩略图
  11. 用户活跃、留存、流失,终于讲清楚了!
  12. 爬虫(七)通过Selenium爬取网易云音乐评论
  13. 关于闲鱼测试数据构造,我有几条心得
  14. PhpStorm在上传文件的时候提示 Upload to 虚拟机 failed: invalid descendent file name \.
  15. 安卓圆形图片控件CircleImageView的使用
  16. html5播放加速,html5倍速播放插件
  17. UEFI下安装win10
  18. C#NPOI 往excel里面追加一行或者一个Datatable
  19. linux go设置阿里云代理
  20. 什么叫五口POE交换机 五口POE交换机使用方法

热门文章

  1. [NOIP2015提高组]运输计划
  2. Win8下怎样安装Win7 or Win7下怎样安装win8?
  3. 关于c#调用c编译器
  4. js 编程时注意事项
  5. Rails 开发小贴士积累
  6. SharePoint Timer Job
  7. 项目中的模块剥离成项目_使用MCEBuddy 2从电视录制中剥离广告
  8. powershell 变量_极客学院:学习PowerShell变量,输入和输出
  9. 诈骗者如何伪造电子邮件地址,以及如何分辨
  10. 使用ArcGIS Server发布我们的数据