如果您执行大量读取但很少更新,则缓存很有用.数据库中的数据越频繁,缓存系统就越成问题.缓存确实会给代码库增加一定的复杂性,这可能很难处理.它甚至可以在最糟糕的情况下减慢你的网站速度.
最重要的问题是:
什么时候必须使缓存无效?什么时候变得陈旧?在大多数情况下,如果数据库查询返回的行数与缓存该页面时的行数不同.但你怎么知道的?你没有(也许有办法,但我想不出任何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到占位符中.回应结果.
如果条目被更改或有人注释,则必须删除带有条目id的缓存文件.
这是惰性缓存 – 仅当用户请求页面时才构建缓存.小心 – 如果用户在注释中键入{username},它也会插入到那里!这意味着,您必须在str_replacing之后转义缓存的数据并对其进行转换.这种技术也适用于memcached或apc.
问题:你必须围绕缓存设计构建你的设计.例如如果你想显示“5分钟前发布的评论”而不是“5月6日下午3:42添加评论”,那么你就麻烦了.