专栏名称: 算法爱好者
算法是程序员的内功!伯乐在线旗下账号「算法爱好者」专注分享算法相关文章、工具资源和算法题,帮程序员修炼内功。
目录
相关文章推荐
算法爱好者  ·  DeepSeek ... ·  19 小时前  
九章算法  ·  Meta学神刷题奥义!《LeetCode通关 ... ·  5 天前  
九章算法  ·  「九章快讯」Meta大裁休长假的员工! ·  5 天前  
51好读  ›  专栏  ›  算法爱好者

那些年我们一起追过的缓存写法(二)

算法爱好者  · 公众号  · 算法  · 2017-05-23 20:00

正文

(点击 上方公众号 ,可快速关注)


来源:蘑菇先生

cnblogs.com/mushroom/p/4257342.html

如有好文章投稿,请点击 → 这里了解详情


上次 那些年我们一起追过的缓存写法(一) 主要讨论缓存读写这块各种代码实现,本篇就上次的问题继续来,看看那些年折腾过的各种缓存做法。


缓存预热


上次有同学问过,在第一次加载时缓存都为空,怎么进行预热。


单机Web情况下一般使用RunTimeCache,这种情况下:


可以在启动事件里面刷新


void Application_Start(object sender, EventArgs e)

{

//刷新

}


另外可以单写个刷新缓存页面,上线后手动刷新下或发布时自动调用刷新,再或者由用户自行触发。


分布式缓存(Redis、Memcached)情况下:


比如在几十台服务器缓存时,单刷满缓存都需要不少一段时间。


这种预热就复杂一些,有的会单写个应用程序去跑,也有的会单写套框架机制去处理(更智能化)。


其目的是在系统上线之前,所有的缓存都预先加载完毕。


多级缓存


计算机结构中CPU和内存之间一般都配有一级缓存、二级缓存来增加交换速度。


这样当CPU调用大量数据时,就可避开内存直接从CPU缓存中调用,加快读取速度。


根据CPU缓存得出多级缓存的特点:


  1. 每一级缓存中储存的是下一级缓存的一部分。

  2. 读取速度按级别依次递减,成本也依次递减,容量依次递增。

  3. 当前级别未命中时,才会去下一级寻找。


而在企业应用级开发中,使用多级缓存是同样的目的及设计,只是粒度更粗,更灵活。


根据速度依次排列lv1-lv6的缓存类型图:




3级缓存的命中流程图例子:



线程缓存


Web应用是天生的多线程开发,对于一些公共资源必须考虑线程安全,为止不得不通过锁来保证数据的完整性和正确性。


在实际当中一台web服务器至少也得处理成百上千的请求,想一想在业务复杂的处理流程,函数每调用一次都得锁一下,对服务器也是个不小的浪费。


而通过线程缓存,可以让当前处理用户请求的线程只拿自己需要的数据。


public static ThreadLocal localUserInfo = new ThreadLocal ();


借助Net提供的线程本地变量,可以在请求入口去拉取当前用户的数据。


在之后线程整个生命周期里面,业务逻辑可以毫无顾虑的使用这些数据,而不需要考虑线程安全。


因为不用重新拿新缓存数据,所以也不用担心数据撕裂的问题。


其当前线程周期里面的数据是完整无误的,只有用户第二次发起请求才会重新去拿新数据。


这样就能提高不少服务器吞吐量,注意要在线程的出口处销毁数据。


内存缓存


无论是远程数据库读取,还是缓存服务器读取。避免不了要跨进程,跨网络通信,有的还跨机房。


而应用程序频繁读写,对Web、DB服务器都是个不小的消耗,速度相较内存也慢的多。


代码上加锁、异步,甚至加服务器在内,都不是一个很好的办法。因为加载速度,对用户体验非常重要。


所以在有要求的项目中使用本地内存做二级缓存,是非常有必要的。目的就是1:抗并发,2:加快读取速度。


有个著名的缓存五分钟法则法则,就是说如果一个数据频繁被访问,那么就应该放内存中。


举个例子: 有100并发过来,加锁会导致前端99线程等候,这个99线程等候着,其实是一直在消耗Web服务器资源。不加就是缓存雪崩。


如果每分钟拉取一份缓存,缓存到内存,这样99线程等候时间极大缩短。


文件缓存


相对于内存,硬盘容量大,速度相较于走网络还更快。


所以我们完全可以把一些不经常变更,放在内存又比较浪费的数据缓存到本地硬盘。


比如使用sqlite一些文件数据库,我们很容易做到。


分布式缓存


基于内存缓存的redis、memcached等。








请到「今天看啥」查看全文