缓存策略基础初探
一、引言
由于我个人对于缓存这块内容基础极为薄弱,在不久前一次面试中被逮着问了,当时大脑空空如也,对于缓存只能蹦出几个零零散散的片段:ecache,redis,读取缓存数据代替内存来优化读写速度,Map存储。所以那次面试也毫无悬念的GG了。没办法,只能从头来学习下缓存这块内容。
二、缓存基础
1、什么是缓存
要想了解一个事物,就得从源头知道这东东是啥?为什么要有它?它存在的作用?
这些概念性的描述就借用现成的啦:
- 缓存就是数据交换的缓冲区(称作:Cache),当某一硬件要读取数据时,会首先从缓存汇总查询数据,有则直接执行,不存在时从内存中获取。由于缓存的数据比内存快的多,所以缓存的作用就是帮助硬件更快的运行。
- 缓存往往使用的是RAM(断电既掉的非永久存储),所以在用完后还是会把文件送到硬盘等存储器中永久存储。电脑中最大缓存就是内存条,硬盘上也有16M或者32M的缓存。
- 高速缓存是用来协调CPU与主存之间存取速度的差异而设置的。一般CPU工作速度高,但内存的工作速度相对较低,为了解决这个问题,通常使用高速缓存,高速缓存的存取速度介于CPU与主存之间。系统将一些CPU在最近几个时间段经常访问的内容存在高速缓存,这样就在一定程度上缓解了由于主存速度低造成的CPU“停工待料”的情况。
- 缓存就是把一些外存上的数据保存在内存上而已,为什么保存在内存上,我们运行的所有程序里面的变量都是存放在内存中的,所以如果想将值放入内存上,可以通过变量的方式存储。在JAVA中一些缓存一般都是通过Map集合来实现的。
上述内容很好地回答了前面的问题。至于缓存的作用,被我引用的那篇文章也描述的很好,下面再次不要脸地抄一段:
缓存在不同的场景下,作用是不一样的:
- 操作系统磁盘缓存 ——> 减少磁盘机械操作。
- 数据库缓存——>减少文件系统IO。
- 应用程序缓存——>减少对数据库的查询。
- Web服务器缓存——>减少应用服务器请求。
- 客户端浏览器缓存——>减少对网站的访问。
而我们平时做Java开发常接触到的应该就是2、3、4了吧,下面我就从这几个方面入手开始学习。
2、数据库缓存
下面先拿最常用的mysql数据库来说吧。mysql数据库是通过QC(Query Cache)来实现数据库缓存的,当开启QC(默认是开启的,要关的话,把query_cache_size/type的值设成0,永久关闭就到mysql的配置文件里该)后,数据库会在执行select时,将其结果存储到QC,之后若再调用相同的SQL,就不会再去访问数据库表。直接从QC取值,这样一来是不是快了很多呢?
不过,这样做会有个问题,如果在数据进行缓存之后,原来的数据库表数据发生了更改,那么从QC取出来的数据就是错误的了。因此QC有个对应的机制,如果数据库表发生更改,那么这个数据库表相关的所有缓存都会失效。
根据QC的特点可知,要做mysql的查询缓存,该数据表的数据变动频率应该要比较小,否则碰到经常变动的表,缓存频繁失效,那开不开QC其实区别不大。
顺便扩展下除了开查询缓存外mysql查询优化的几个长考虑到的点:
-
加索引(这个是最常用的了);
-
看慢查询日志,查看需要优化的SQL。加了索引开了QC之后还是觉得很慢,就需要查下慢查询日志了
,开启方法为:set global slow_query_log = 1; 1为开启 0为关闭,此外,再介绍几个相关的参数(slow_query_log_file 记录日志的文件名;log_queries_not