分享

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

 太极混元天尊 2018-05-18


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



文 | WiconWang (新浪高级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缓存技术


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










    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多