从原理到场景 系统讲解PHP缓存技术

从原理到场景 系统讲解PHP缓存技术



使用缓存技术解决各环节瓶颈问题,是IT工程师的基本要求。



文 | WiconWang (新浪高级PHP工程师)

引言



我在慕课网最新教程《从原理到场景 系统讲解PHP缓存技术》详细解析了一个网站架构各个环节中,涉及到缓存的各种原理,以及它们各自的应用场景和适用对象。



从原理到场景 系统讲解PHP缓存技术

本文我带大家再了解一下各种缓存使用后,还有什么可以优化的地方?







一:浏览器缓存

浏览器缓存有两个使用原则:

一个是加大本地缓存的复用性,比如一些不经常改变的静态资源,比如图片、CSS、JS,尽量利用本地缓存,主要的通过Cache-Control:max-age 和 Expires 来进行控制,过期之后则使用 Last-Modified 来进行协商控制。



对于PHP生成的动态资源,如果不经常进行内容改变的话,可以用

 header() 

主动输出这些文件头。

另一个是尽量减少对服务器的请求量,这个主要集中在页面请求的时候,尽量把多个请求量,合并成一个,比如多个JS合并为一个,把多个小图标并成一个文件,然后就可以统一进行缓存。





二:DNS相关缓存

域名解析也是一个比较耗时间的地方,尽量使用Keep-alive,出来重用TCP-IP连接减少相应时间。

另外一个就是和京东淘宝一样,启用多个域名,来绕过浏览器域名的并发限制,让所有域名同时进行下载减少时间消耗,但注意,域名越多,dns解析也越多,因此这一项是需要按照需求进行平衡的。



三:WebServer相关

启用反向代理服务器,这个服务器不应该仅仅有请求转发的作用,而是应该配置为动态资源转发、静态资源进行缓存和加速,这样可以减少对应用服务器的压力,应用服务器也可以将一些生成的静态化资源,分发到反向代理服务器,使之成为一个缓存节点。

服务器在建设的时候,考虑到异步架构,对于一些非紧急处理的需求,进入消息队列进行处理,一旦主服务器出现故障或其他紧急需求,可以优先处理主服务器的需求,等待处理完成之后,继续处理消息队列。



四:Mysql相关

Mysql的缓存相对来说比较小,而且开关均有资源消耗,所以使用它需要谨慎,它比较适合存储一些消耗大量资源进行的查询,如汇总计算、连表、分页、排序等复杂查询。

缓存命中率相关参数,可以在命令行中使用

 

show global status

 查询到,用 

Qcache_hits / (Qcache_hits + Com_select)

 来计算出来大约的命中率。不过实际查询缓存的命中率其实比较难以判断,可以通过禁用查询缓存,再重新打开,来判定对应的SQL是否已经触发了查询缓存?

一些查询语句中不确定的参数,如rand 、current_data 、查询结果过大等,都会导致无法进行缓存,另外查询缓存空间用光也会导致缓存的失效。除此之外,对于INNODB来说,表上启用了任何一个锁,都会导致该表的任何查询语句无法缓存。

由于Mysql查询缓存限制比较多,因此对于复杂的缓存需求,建议使用第三方缓存,比如Redis。

五:Redis

主要关注三个指标: 缓存命中、缓存一致性、缓存失效。

5.1 Redis的缓存命中

这个不多说了。多查询日志和键值就能比较直观地算出命中率。尽量提高热点数据的命中率,以保证业务的高效性。

5.2 Redis的缓存一致性

同步方案

:当有数据更新的时候,如果没有命中缓存直接更新数据库。如果命中了缓存,则更新缓存,然后更新数据库,这种可以比较好的保证缓存一致,代价是每一个请求都需要等待非内存部分,有较大的时间消耗,比较适用于强一致性,弱性能的需求。



异步方案:

更新数据的时候,只更新缓存不更新数据库,然后直接返回,后续启用队列异步地批量更新数据库。这种方案响应速度快,比较适用于数据弱一致,但对性能要求高的需求中。

5.3 Redis的缓存失效

Redis在使用缓存的时候,每一个key都要设置对应的过期时间,但是注意这些时间应该都不一致,比如对于商城来说,用户访问首页的时候,就会同时生成很多的缓存,如果这些缓存的时间都相同,就会在同一个时间进行失效,一旦失效之后用户再进行访问,就需要同时生成所有缓存,这个时间点就会出现比较大的服务器压力。



解决方案很简单,生成缓存的时候,把过期时间设置成一个时间点外加一点随机数,这样首页中生成的所有缓存的时间就都不一致了,在一定程度上分散了缓存失效压力,

5.4 Redis及缓存穿透

缓存穿透是指,在缓存中未找到结果,而需要去数据库中继续查询,如果数据库中有记录,那么下一次查询就会被加速。

但是经常会出现的场景是,在数据库中也未找到对应记录,这样的话,每次请求依然会在数据库重新进行检索,如果这个请求是非常复杂的一种,这会造成比较大的流量压力

这种情况一般有两个解决方案:

一个是当查询数据为空的时候,把空结果也进行缓存,这样下次在检索的时候,就可以取到缓存内容了。

另外呢,也可以启用一个保护机制,增加一个标记key,用来标记原来的key。 当标记key存在的时候,直接返回null。 这种机制在实现的时候比较麻烦,主要是用于标记那些查询过于复杂的那些请求。

以上这些是我对课程的补充。

如果对如何在具体项目中应用缓存?

哪些场景应该使用哪些缓存?



可以订阅我的教程

《从原理到场景 系统讲解PHP缓存技术》

,订阅后可永久观看。

从原理到场景 系统讲解PHP缓存技术

这门课程以电商网站为例,通过具体场景模块实战,让你更系统的掌握缓存原理、使用场景等相关知识,帮助你构建完整的缓存知识体系,胜任实际开发中缓存的处理,提升代码性能!

从原理到场景 系统讲解PHP缓存技术

从原理到场景 系统讲解PHP缓存技术

从原理到场景 系统讲解PHP缓存技术

从原理到场景 系统讲解PHP缓存技术



教程学习地址

点击下方图片,即可查看



从原理到场景 系统讲解PHP缓存技术



从原理到场景 系统讲解PHP缓存技术

从原理到场景 系统讲解PHP缓存技术
     

从原理到场景 系统讲解PHP缓存技术

程序员的梦工厂



让更多热爱互联网的同学来慕课网学习

多年以后,圈子里一批技术牛说:

我在慕课网学习过,这就够了

从原理到场景 系统讲解PHP缓存技术

慕课网

公众号ID:imooc-com

关注

从原理到场景 系统讲解PHP缓存技术
从原理到场景 系统讲解PHP缓存技术

???点击 | 

阅读原文

 | 涵盖完整缓存核心知识