Lot*_*tes 13 php database model-view-controller caching
我在一个关于MVC缓存的相关问题中发表了一些评论,并提出了一些关于实际实现的问题.如何在没有开发人员需要手动缓存的情况下实现透明工作的模型级缓存,但仍然保持高效?
我会将我的缓存职责牢牢地放在模型中.它不是模型获取数据的控制器或视图业务.他们关心的是,当请求数据时,提供数据 - 这就是MVC范例应该如何工作的.
(来源:Jarrod发布)
我怀疑的原因是,除非有真正的需要,否则通常不应该进行缓存,不应该对搜索结果这样的事情进行缓存.因此,模型本身必须知道发给它的SELECT语句是否值得缓存.模型不是必须天文学上聪明,和/或存储长时间最常查询的内容的统计数据,以便准确地做出决定吗?并不是所有这些的开销不会使缓存无用吗?
如何从另一个查询中唯一标识查询(或者更确切地说,从另一个结果集中识别结果集)?如果您使用预准备语句,只根据用户输入改变参数,那该怎么办?
另一张海报说:
我建议使用查询的md5哈希值和输入参数的序列化版本.
碰撞的微小机会值得担心吗?
从概念上讲,模型中的缓存似乎对我来说是一个好主意,但它看起来很实用,并且由于缓存的性质,开发人员应该直接控制它并明确地将其编码到控制器逻辑中.
更新赏金
我确实使用了一个非常轻量级的ORM,有点类似于ActiveRecord,但是能够在没有n^2问题的情况下进行复杂的连接和子查询.我自己构建它,所以它很灵活,并且在关系或列名方面没有限制,我只是想了解我应该如何实现缓存机制.
根据乐于助人的建议,我会将查询的哈希值(可能是md5)与其参数列表连接起来,并将其用作该特定数据存储的键.我应该在需要它的Model类中单独实现缓存,还是应该成为ORM层的一部分?
我怎么知道什么时候应该失效?我是否必须手动解析UPDATE/DELETE/INSERT查询和子参数以找出正在修改的记录?或者更糟糕的是,每当修改数据时都要进行其他查询,以便跟踪哪些内容发生了变化,哪些内容应该失效?
我将奖励那些可以给我一个明确的概念性解释的人(无论这是否真的必须/有效地透明地完成),如果是这样,有一些模型缓存的实现细节.我正在使用PHP和MySQL,如果这有助于缩小你的注意力.
缓存有很多因素需要考虑,例如散列,失效等.但缓存的目标始终是相同的:减少响应时间和资源消耗.
对于不使用ORM的系统,我有几个快速的想法:
SELECT查询,因为其他类型会影响数据serialize()参数的d版本连接的查询的md5 (这标识了唯一的查询.由于通常传递给选择查询的参数的大小通常非常简单,因此查找参数不是问题).序列化并不像您想象的那么昂贵.而且因为你将静态查询与动态参数连接在一起,所以你永远不必担心碰撞.INSERT/ UPDATE/ DELETE)模型中的行应该对该模型缓存的所有项目无效(或设置TTL)ORDER BY/ LIMIT类型操作通常更有效,而不是从缓存中提取整个行集并通过PHP操作它来实现相同的目的(除非有非常Web和数据库服务器之间的高延迟).尝试管理ORM系统的缓存验证是一种完全不同的野兽(由于关系),并且应该根据具体情况(在控制器中)进行处理.但是,如果你真的关心性能,你可能不会开始使用ORM.
更新:
如果您发现自己在单个线程中使用同一模型类的多个实例,我建议还可能对实例化模型进行内存缓存(取决于您的构造函数,反序列化和唤醒对象有时比构造对象更有效).一旦你有一个初始化对象(无论是构造的还是反序列化的),它对于一个对象的基本实例来说更有效,clone()并设置它的新状态而不是在PHP中重建一个对象.
如果模型是一个简单的ORM,那么你的帖子才有意义.并且有很多原因可以解释为什么这是一件坏事.尝试将模型视为Web服务.
缓存是模型的责任.
如何从另一个查询中唯一标识查询(或者更确切地说,从另一个结果集中识别结果集)?如果您使用预准备语句,只根据用户输入改变参数,那该怎么办?
但是模型的输入唯一地定义了它的输出.
如果您使用相同的模型来检索购物篮的内容并在产品目录上运行搜索,那么您的代码就会出现问题.
即使在购物篮的情况下,缓存数据的优点在于TTL小于处理将改变其内容的交易所花费的时间,在目录搜索的情况下,缓存匹配产品的列表以用于几个小时可能对销售没有可衡量的影响,但在减少数据库负载方面做得很好.
您使用简单的ORM开箱即用的事实并不排除您将其包装在您自己的代码中.
模型不是必须天文学上聪明,和/或存储统计数据
否.您可以确定是否要缓存,如果无法确保缓存是一致的,则根据请求类型强制执行TTL.
作为一般经验法则,您应该能够在绑定任何变量之前基于SELECT查询预测适当的TTL ,这需要在设计时实现 - 但显然结果应该基于绑定后的查询进行索引.
我应该在需要它的Model类中单独实现缓存,还是应该成为ORM层的一部分?
首先,我会将其作为模型类的装饰器实现 - 这样您就可以轻松地将其移植到实现工厂而不是简单的ORM的模型中.
C.