我已经阅读了几个关于实现php缓存系统的指南(我的网站是自定义编码的,相当严重的查询和不断增长),包括以下内容:http://www.snipe.net/2009/03/quick-and-dirty-php -caching /
我完全理解它们,但页面的某些部分我无法缓存,最好的方法是什么?
如果您执行大量读取但很少更新,则缓存很有用.数据库中的数据越频繁,缓存系统就越成问题.缓存确实会给代码库增加一定的复杂性,这可能很难处理.在最糟糕的情况下,它甚至可以减慢你的网站速度.
最重要的问题是:
什么时候必须使缓存无效?什么时候变得陈旧?在大多数情况下,如果数据库查询返回的行数与缓存该页面时的行数不同.但你怎么知道的?你没有(也许有办法,但我想不出任何atm),因为要检查一下,你可能要查询结果进行比较.
你可以做什么:
每次更新数据库的相关部分时清除所有缓存,
如果您的数据库很少得到更新(每小时,每天,每周),这确实是可能的.但如果不断变化,它就没用了.大多数网络项目就是这种情况.
事情发生后清除缓存的项目
只有在不必立即反映更改时才有效(例如,如果一段时间内数据不正确则无关紧要).在这种情况下,如果某个项目超过X分钟,或者超过Y页面浏览量,您只需清除某个项目的缓存即可.
只清除相关部分
,您必须确定在更新数据库时哪些部分的缓存会受到影响.如果做得好,改变会在性能提高时立即反映出来.
大多数人都是选项3:你必须找出答案.因此,举一个例子,让我们看一下博客的经典案例,包括首页,档案页面和每个条目的详细页面.
更改由以下内容引入:管理面板(条目的crud)和注释
如果条目被编辑或删除,则必须清除缓存:
首页,如果条目是新的
相关的存档页面,如果条目是旧的
条目的详细页面
如果有人推荐您只需要清除详细信息页面,但前提是注释或存档中没有显示注释数量.否则,与入口 - crud相同.
如果站点范围内的某些内容发生了变化,则必须清除整个缓存(不好!)
现在,让我们考虑入口和存档.如果存档的类型为"每月一页",则清除该条目所属的月份.但如果存档是1-10,11-20,21-30的条目,那么大多数情况下整个存档缓存都必须重建.
等等 ...
一些问题:
如果您没有正确识别所有受影响的部分,则可能导致陈旧数据和/或(非)死链接.
如果更新经常发生,那么构建缓存是额外的工作,因为当下一个页面视图发生时,缓存很可能再次失效并且无论如何都必须重建.
页面的某些部分不适合缓存,例如(自定义)搜索功能.如果缓存在其他地方工作,一切都很快很好,但搜索速度仍然非常慢.
如果在发生大量请求时必须清除整个缓存,则可能会出现问题.然后它可以阻塞你的服务器,因为缓存缺失通常比首先没有缓存页面更昂贵.更糟糕的是,如果有3个请求进入,并且第一个请求在处理其他两个请求之前无法缓存页面,则缓存会被请求3次而不是一次.
我的建议:
优化您的数据库.键和配置好吗?也许它没有缓存.
优化您的查询."解释选择"!
只缓存页面的部分 - 昂贵的.使用str_replace和占位符填写小的,廉价的更改
如果一切正常,请使用apc或memcached而不是文件(文件通常效果很好,但apc/memc更快).您也可以使用您的数据库来缓存您的数据库,这通常很有用!
你在建立一个懒惰或急切的缓存系统?懒惰意味着:在页面首次请求时构建缓存,急切意味着:在更新后立即执行.
嗯,我对你没有任何真正的建议.过分依赖于问题:)
这是一个带有密钥256的博客条目请求.它显示了博客条目,评论和当前登录的人.查询条目和评论以及格式化所有文本和所有内容都很昂贵.当前登录的用户驻留在会话中.
首先,为要缓存的部分创建唯一键.在这种情况下,缓存键可能是条目的数据库ID(带有一些前缀和后缀).
所以,缓存的文件应该有名称cache/blogentry_256.tmp
.检查,如果该文件存在.
如果它不存在,请执行所有昂贵的查询和格式化,留下占位符(例如{username}),其中应包含当前用户的名称并保存结果cache/blogentry_256.tmp
.注意不要将任何数据写入此文件,不应为每个人显示或每次请求都要更改.
现在,读取文件(或重用1中的数据)并将用户名str_replace到占位符中.echo
结果.
如果条目被更改或有人注释,则必须删除带有条目id的缓存文件.
这是惰性缓存 - 仅当用户请求页面时才构建缓存.小心 - 如果用户在注释中键入{username},它也会插入到那里!这意味着,您必须在str_replacing之后转义缓存的数据并对其进行转换.这种技术也适用于memcached或apc.
问题:你必须围绕缓存设计构建你的设计.例如,如果你想显示"5分钟前发布的评论"而不是"5月6日下午3:42添加评论",那么你就麻烦了.