Php 实现模型级缓存

Php 实现模型级缓存,php,database,model-view-controller,caching,Php,Database,Model View Controller,Caching,我在一篇关于MVC缓存的文章中发表了一些评论,并提出了一些关于实际实现的问题。如何实现一个模型级缓存,它可以透明地工作,而不需要开发人员手动缓存,但仍然保持高效 我会保留我的缓存 公司内部的责任 模型它不是控制器的 或者查看模型所在的业务 获取数据。他们关心的只是 当请求数据时,数据 提供-这是MVC的工作方式 范式应该是有效的 (来源:) 我对此持怀疑态度的原因是,除非有真正的需要,否则通常不应该进行缓存,也不应该对搜索结果之类的事情进行缓存。因此,模型本身必须知道向其发出的SELECT语句是

我在一篇关于MVC缓存的文章中发表了一些评论,并提出了一些关于实际实现的问题。如何实现一个模型级缓存,它可以透明地工作,而不需要开发人员手动缓存,但仍然保持高效

我会保留我的缓存 公司内部的责任 模型它不是控制器的 或者查看模型所在的业务 获取数据。他们关心的只是 当请求数据时,数据 提供-这是MVC的工作方式 范式应该是有效的

(来源:)

我对此持怀疑态度的原因是,除非有真正的需要,否则通常不应该进行缓存,也不应该对搜索结果之类的事情进行缓存。因此,模型本身必须知道向其发出的SELECT语句是否值得缓存。为了准确地做出决策,该模型是否必须具备天文智能,和/或存储长期以来最常被查询的数据?这一切的开销难道不会让缓存变得毫无用处吗

如何从另一个查询(或者更准确地说,从另一个结果集中的结果集)中唯一地标识一个查询?如果您使用的是预先准备好的语句,并且只有参数根据用户输入而改变,那么会怎么样

另一张海报上写着:

我建议使用 您的查询与序列化 输入参数的版本

碰撞的极小可能性值得担心吗

从概念上讲,在模型中缓存对我来说似乎是一个好主意,但在实践中,由于缓存的性质,开发人员应该直接控制它,并明确地将其编码到控制器逻辑中


赏金更新

我确实使用了一个非常轻量级的ORM,它有点类似于ActiveRecord,但能够进行复杂的连接和子查询,而不会出现
n^2
问题。我自己构建的,所以它是灵活的,在关系或列名方面没有限制,我只是想了解应该如何实现缓存机制

按照帮助人员的建议,我将获取一个与参数列表连接的查询哈希(可能是md5),并将其用作特定数据存储的键。我应该在需要缓存的模型类中单独实现缓存,还是应该将其作为ORM层的一部分

我怎么知道它什么时候应该失效?我是否必须手动解析更新/删除/插入查询和子in参数,以确定哪些记录正在被修改?更糟糕的是,每当数据被修改时,是否进行额外的查询,以跟踪哪些内容发生了更改,哪些内容应该失效


我将把奖金奖励给任何能给我一个清晰概念性解释的人(这是否真的有必要/有效地透明地完成),如果是,则提供一些模型缓存的实现细节。我使用PHP和MySQL,如果这有助于缩小你的焦点。

缓存中有很多因素需要考虑,例如散列、无效等。但是缓存的目标总是相同的:减少响应时间和资源消耗。

以下是我头脑中关于不使用ORM的系统的一些快速想法:

  • 如果你有足够的内存,那么使用memcache缓存东西是不会有任何伤害的
  • 您应该只缓存
    选择
    查询,因为其他类型会影响数据
  • 所有缓存的查询都应该参数化
  • 缓存键应该是查询的md5,与参数的
    serialize()
    'd版本连接在一起(这标识唯一的查询。序列化参数不是问题,因为通常传递给选择查询的参数的大小通常非常小)。序列化并不像你想象的那么昂贵。而且,由于您将静态查询与动态参数串联在一起进行散列,因此您不必担心冲突
  • 对模型中行的修改(
    插入
    /
    更新
    /
    删除
    )应使该模型缓存的所有项失效(或设置TTL)
  • 应该扩展该模型,以允许缓存TTL值随查询一起发送
  • 您的模型应该支持跳过缓存(可能通过将TTL 0与查询一起传递)
  • 即使可以缓存基本查询,在新的(修改的)查询中应用
    ORDER BY
    /
    LIMIT
    类型操作通常比从缓存中提取整个行集并通过PHP对其进行操作来实现同样的效果更为有效(除非web和数据库服务器之间存在非常高的延迟).
尝试管理ORM系统的缓存验证是一个完全不同的问题(由于关系),可能应该(在控制器中)逐个处理。但是,如果您真正关心性能,那么您可能不会从一开始就使用ORM

更新:


如果您发现自己在一个线程中使用同一个模型类的多个实例,我建议您也可以对实例化的模型进行memcaching(根据您的构造函数,反序列化和唤醒对象有时比构建对象更有效)。一旦你有了一个初始化的对象(无论是构造的还是反序列化的),它将比在PHP中重建一个对象更有效

您应该有一个单独的模型,直接进行SQL接口,例如,对于客户表:
$CustomerModel->GetCustomers($parameter)等等。然后,在这些模型中,您可以实现透明缓存