php - memcached 数据缓存的设计模式

标签 php database design-patterns oop memcached

围绕现有数据库查询包装可选的 memcached 缓存很容易。例如:

旧的(仅限数据库):

function getX
    x = get from db
    return x
end

新(带内存缓存的数据库):

function getX
    x = get from memcache
    if found
      return x
    endif

    x = get from db
    set x in memcache
    return x
end

但问题是,这并不总是您想要的缓存方式。例如以下两个查询:

-- get all items (recordset)
SELECT * FROM items;

-- get one item (record)
SELECT * FROM items WHERE pkid = 42;

如果我使用上面的伪代码来处理缓存,我将存储项目 42 的所有字段两次。一次创下大纪录,一次独树一帜。而我宁愿做这样的事情:

SELECT pkid FROM items;

并缓存 PK 的索引。然后也单独缓存每条记录。

总而言之,最适合数据库的数据访问策略并不完全适合内存缓存策略。由于我希望 memcache 层是可选的(即,如果 memcache 关闭,该站点仍然有效)我有点想两全其美,但要做到这一点,我很确定我需要维护一个许多查询有两种不同的形式(1. 获取索引,然后获取记录;2. 在一个查询中获取记录集)。分页变得更加复杂。使用数据库,您可以执行 LIMIT/OFFSET SQL 查询,但使用内存缓存,您只需获取 PK 的索引,然后批量获取数组的相关切片。

我不确定如何巧妙地设计它,有人有什么建议吗?

更好的是,如果您自己遇到过这种情况。你是怎么处理的?

最佳答案

如果您正在使用缓存,那么为了充分利用它,您必须接受您的数据在一定程度上总是过时的,并且数据的某些部分将彼此不同步.尝试通过维护单个副本来使所有记录保持最新是最好留给关系数据库的事情,因此如果这是您需要的行为,那么您可能最好使用具有大量 RAM 的功能强大的 64 位数据库服务器因此它可以执行自己的内部缓存。

如果您可以接受陈旧数据(如果真正的可伸缩性很重要,您将需要这样做),那么一种方法是将整个结果集放入缓存;不用担心重复。内存很便宜。如果您发现缓存已满,则只需购买更多 RAM 和/或缓存服务器即可。例如,如果您有一个查询表示按条件 X 和 Y 过滤的集合中的项目 1-24,则使用包含所有这些信息的缓存键,然后当再次要求进行相同的搜索时,只需返回整个结果集缓存。您要么一次从缓存中获取完整的结果集,要么转到数据库。

最困难的事情是弄清楚有多少数据可以过时,以及在 (a) 人们没有注意到太多,或 (b) 违反业务要求(例如最小更新间隔)的情况下可以过时到什么程度。

这种方法适用于以读取为主的应用程序,尤其是那些具有分页查询和/或一组有限的数据过滤条件的应用程序。这也意味着您的应用程序在缓存打开或关闭时的工作方式完全相同,只是缓存关闭时的命中率为 0%。在几乎所有情况下,这都是我们在 blinkBox 中采用的方法。

关于php - memcached 数据缓存的设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/276709/

相关文章:

database - 只读数据库访问的事务?

design-patterns - 这种类似 monad 的函数式编程模式叫什么名字?

php - 维护活跃用户列表并在虚拟主机上检索它

php - 在 mysql 查询中使用 php 数组

MySQL 计算别名计数列的平均值

database - 顶级数据库的搜索算法

c# - 设计模式中枚举的替代方案

Java过滤器工厂实现

php - 在循环下拉函数中运行 mysql count 命令

PHP - 一个方法可以返回一个指针吗?