ThinkPHP缓存源码深度解析(1)

本文涉及的产品
云解析DNS-重点域名监控,免费拨测 20万次(价值200元)
简介: ThinkPHP缓存源码深度解析

前言

在项目中缓存是必不可少的一项功能,当用户量大的时候是必须上缓存的,如何都直接查数据库那么对于用户体验来说就太差了。


那么什么情况下应该使用缓存呢!


  • 热点事件,例如微博热搜
  • 不经常更新的数据,例如配置项
  • 博客平台的排行榜单
  • 社交平台的关注列表粉丝列表等等

以上说的这些应用场景并不说是框架的缓存,一般在使用缓存的层面是不太使用框架的缓存的。


常用的为redis,memcache等NoSQL。


但是今天主要讨论的是框架中缓存,所以千万不要认为框架的缓存是无所不能的,还是要看项目的实际情况。


一、缓存cache设置的执行流程以及源码解析

首先需要实现以下的案例,并且引入cache类


image.png


cache怎么运行的?


就代码Cache::set这个现在知道是怎么运行的吗?如果不知道咔咔带你在来深入的学习一次。


我们都知道框架的入口文件是index.php,在入口文件中引入了一个文件为base.php。


image.png


来到base.php这个文件里边可以看到关于注册类库别名,至于是怎么注册的,这个在框架执行流程的那一节中有过深度的讲解,可以回过头在去了解一下。


image.png


所以说代码将会执行到框架核心的facade这个类里边,在这个类里边存在一个方法__callStatic,当调用不存在的静态方法时此方法会进行执行。


image.png


那么怎么来做这个验证呢!不能咔咔这样说就是这样的对吧!


那么代码将会接着来到创建Facade实例这个方法,我们做的测试就是将这个class打印出来得到的值都有什么。


image.png


暂时先不管这个cache执行了几次,是可以明显的看到打印结果是存在这个值的,所以说从另一个笨拙的方面验证了咔咔的说辞。


image.png


这里有一个特别小的细节我想大家应该需要了解一下,那就是关于static的使用


关于static的小技巧


首先可以看到cache类是继承这Facade门面类


image.png


然后static是在门面类中做的使用,那么最终返回的类就是继承门面类的那个类也就是cache类


image.png


总结为一句话就为


static 如果有被继承的话 默认调用子类 ,否则调用的是自身


所以说下边接着的static::getFacadeClass()这里也是执行的子类中的方法。


好了,进入了一段小插曲,接下来会到正题。


所以说代码将会执行到thinkphp/library/think/Cache.php这个文件,也就是核心类库的位置。


在这个方法你是找不到set方法的,所以代码将会执行到__call方法,这个方法当调用不存在的方法时则会触发的方法。


image.png


自动初始化缓存


根据执行流程我们将会看到init这个方法自动初始化缓存(这里需要注意,第一次并不是在这里进行执行的,而是make方法,当make方法执行完后会把值存放在handler这个属性,第二次通过call方法进来之后就直接返回了,而不会在进行一次执行,这里一定要注意)


image.png


在这里我们进行打印一次$options这个的值。


image.png


探讨一下为什么$options这个参数会有值


这里就是关于容器方面的知识了,来咔咔带你看一下。


image.png


当在创建Cache时创建Facade实例,在这个过程中注意咔咔下图圈起来的部位,执行了一个见了八百次的make方法了。


image.png


来到make方法只需要看咔咔圈起来的地方即可


image.png


然后在进入到invokeClass方法,这个方法是调用反射执行类的实例化 支持依赖注入。


在这个方法中通过反射执行了Cache中的make方法。


image.png


所以就会执行Cache类中的make方法,这个方法就会进行实例化本类,并且执行构造函数,接下来看一下。


image.png


来到构造函数中你会看到从make方法获取到的cache配置文件的配置项传进了init方法,也就是自动初始化缓存的部分。


image.png


所以从这里看到init方法自动初始化缓存第一次执行是在容器实例化的时候执行的所以$options才会存在值。


接下来将顺着这个流程进行连接缓存也就是代码$this->handler = $this->connect($options);这块的内容。


这个方法就很简单了,就是使用了之前一直讲解的工厂模式实现的加载不同类型的缓存方式。


然后会把返回的对象存放在以$optionsmd5为下标的缓存实例属性$instance里边。


image.png


最终代码会返回给cache中的__call方法,类为object(think\cache\driver\File)方法为set


image.png


于是执行流程会来到下图位置写入缓存


image.png


获取文件名


在这个方法中主要需要理解的一件事情就是在缓存中是如何进行获取具体的文件名然后进行存储数据的。


这个name值就是咱们需要设置的值,wechat。


image.png


然后来到getCacheKey取得变量的存储文件名。


在这个方法中第一步就是通过hash的方式进行类型和缓存值加密,这个options是在本类声明好了的,这里一定要明确。


因为在框架中大量的使用了options这个变量千万不要搞混淆了。


在这个方法中需要明白的就是这个文件名是怎么确定的。


image.png


还是要来到本类的开始位置查看一下这个options的值,在这个类中可以看到上图中使用的加密类型为hash_type就是md5


image.png


然后来到构造函数中可以看到关于path的设置


image.png


在上图中可以看到Container::get('app')这行代码,这行代码就是使用的容器执行的也是make方法,关于这个make方法在容器中起到的作用是十分大的,所以需要好好理解。


然后有一个小细节不知道大家有没有看到,那就是在下方有一个init方法,我们一起去看看这个方法是干什么的。


来到这个方法后你会发现这里是直接按照获取到的缓存文件的路径进行创建文件。


image.png


这时可以查看一下创建的文件,可以看到文件已经创建好了。


image.png


最后通过file_put_contents函数将数据存放至刚刚获取到的缓存文件存放位置


image.png


数据库存储形式就是下图


image.png


直到这里关于框架缓存设置就结束了,其实流程并不难,在这个案例中咔咔使用的文件形式的,至于redis还是其它都是一样的。



相关文章
|
4月前
|
缓存 监控 安全
告别缓存击穿!Go 语言中的防并发神器:singleflight 包深度解析
在高并发场景中,多个请求同时访问同一资源易导致缓存击穿、数据库压力过大。Go 语言提供的 `singleflight` 包可将相同 key 的请求合并,仅执行一次实际操作,其余请求共享结果,有效降低系统负载。本文详解其原理、实现及典型应用场景,并附示例代码,助你掌握高并发优化技巧。
330 0
|
9月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
894 29
|
8月前
|
缓存 NoSQL Go
【LeetCode 热题100】146:LRU 缓存(详细解析)(Go语言版)
本文详细解析了力扣 146 题——LRU 缓存机制的实现方法。通过结合哈希表与双向链表,确保 `get` 和 `put` 操作均在 O(1) 时间内完成。哈希表用于快速查找,双向链表记录访问顺序,支持最近使用数据的高效更新与淘汰。代码以 Go 语言实现,结构清晰,涵盖核心操作如节点移动、插入与删除。此题为面试高频考点,适用于数据缓存、页面置换等场景,掌握后可加深对缓存策略的理解。
435 4
|
9月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
366 4
|
9月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
9月前
|
存储 前端开发 JavaScript
在线教育网课系统源码开发指南:功能设计与技术实现深度解析
在线教育网课系统是近年来发展迅猛的教育形式的核心载体,具备用户管理、课程管理、教学互动、学习评估等功能。本文从功能和技术两方面解析其源码开发,涵盖前端(HTML5、CSS3、JavaScript等)、后端(Java、Python等)、流媒体及云计算技术,并强调安全性、稳定性和用户体验的重要性。
|
9月前
|
负载均衡 JavaScript 前端开发
分片上传技术全解析:原理、优势与应用(含简单实现源码)
分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
7月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
2月前
|
缓存 负载均衡 监控
135_负载均衡:Redis缓存 - 提高缓存命中率的配置与最佳实践
在现代大型语言模型(LLM)部署架构中,缓存系统扮演着至关重要的角色。随着LLM应用规模的不断扩大和用户需求的持续增长,如何构建高效、可靠的缓存架构成为系统性能优化的核心挑战。Redis作为业界领先的内存数据库,因其高性能、丰富的数据结构和灵活的配置选项,已成为LLM部署中首选的缓存解决方案。
|
3月前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
210 1
Redis专题-实战篇二-商户查询缓存

推荐镜像

更多
  • DNS