对于我现在正在从事的项目,我想缓存来自数据库的大多数数据。为了简洁起见,我将在此处使用一个简单博客的示例,并将分页等内容保留下来。
示例: 我有一个包含帖子和类别的博客。帖子可以分配给一个或多个类别。类别当然是帖子的集合。
我提出了以下两种缓存策略:
策略1
使用此策略,我将缓存存储库返回的所有输出。这意味着用于帖子的方法find($id)
将返回单个帖子(如果可用,则从缓存中返回,如果不在缓存中创建)
方法getByCategory($category)
将返回特定类别的所有帖子。如果可用,该列表将来自缓存,如果不可用,则将获取的列表放入缓存中以供后续请求。
策略2
此策略略有不同。它还会缓存我的存储库返回的所有输出,但是实际的帖子仅由find($id)
方法返回的仅。所有其他存储库方法(代表帖子的列表/集合)将仅返回帖子的ID。
然后,这些方法将循环所有id,并使用find($id)
方法获取实际帖子,并为这些id返回所有帖子的数组。
我想说策略2比策略1有很多优势。
首先,帖子仅在缓存中存储一次,因为代表列表的缓存本身不包含帖子(仅帖子的不变ID),这样可以节省空间(特别适用于内存中缓存机制同样,当帖子更新时,我只需要更新(无效/重新填充)该帖子的缓存。所有列表都将自动包含更新的帖子,因为它们只有ID,并且根据该ID单独请求该帖子。
最后,我将能够通过对ID数组进行切片来对结果进行分页,而不是构建能够对结果进行分页的查询(使用OFFSET
/``LIMIT`等”)。
我看到的唯一真正的缺点是第一个请求。 当从一个空的缓存开始并请求一个列表(例如最近的10个帖子)时,需要进行前1个查询以确定哪个10个ID代表此列表中的帖子。然后,对于所有10个id,从数据库中请求实际的帖子,从而导致总共11个查询。 使用策略1时,我在这里只需要1个查询(选择按日期desc排序的10个帖子) 当然,对于后续请求,所有数据均来自缓存,这两种情况下的查询都为0,因此我不认为这是一个破坏交易的行为。 另一个(小的)缺点可能是,策略2需要更多的缓存请求(策略1需要1个请求,而策略1需要1个请求),但是我不知道我是否能够使用Redis之类的内存中缓存机制来注意到这种情况(甚至在快速的SSD磁盘上使用基于文件的缓存)
我很好奇您没有想到的观点和可能的选择。
干杯!