复杂查询的缓存策略/设计模式

标签 caching design-patterns redis architecture azure-sql-database

我们有一个现有的 API,其中包含一个使用 Redis 的非常简单的缓存命中/缓存未命中系统。支持Key搜索。因此,转换为以下内容的查询很容易根据其主键进行缓存。

SELECT * FROM [Entities] WHERE PrimaryKeyCol = @p1

任何后续请求都可以通过主键在 REDIS 中查找实体或故障回复到数据库,然后用该结果填充缓存。

我们正在构建一个新的 API,它将允许通过更多参数进行搜索,将在结果中返回多个条目,并且将处于相当高的请求量下(足以影响我们现有的 DTU SQL Azure 中的利用率)。

查询将可以通过其他几个术语进行搜索,一次搜索中的多个 PK,各种其他 FK 查找列,文本上的 LIKE/CONTAINS 语句等...

在这种情况下,有没有我们可以考虑的设计模式或缓存策略。 Redis 似乎不太适合这些类型的查询。我正在考虑简单地散列查询参数,然后将该散列缓存为键,并将整个结果集缓存为值。

但考虑到 Redis 的键值性质,以及一个实体可能包含在多个查询哈希下的多个结果集中这一事实,这感觉有点天真。

(作为引用,此数据的来源目前是 SQL Azure,我们正在使用 Azure 的托管 Redis 服务。我们还在寻找访问数据库的替代方法,包括对数据进行非规范化、对数据进行 ETL 处理到 CosmosDB,在 Azure 搜索中托管数据,但这样做还有其他影响,包括实现时间、数据的“新鲜度”等...)

最佳答案

就我个人而言,我不会尝试缓存结果,只会缓存单个实体。当我过去做过这样的事情时,我会从实时查询中返回一个 ID 列表,并从我的缓存层中检索单个实体。这样 ID 列表始终是“新鲜的”,并且您不会遇到讨厌的缓存失效逻辑问题。

如果您确实有经常重复出现的搜索,您可以缓存(id 的)结果,但您可能会遇到分页等问题。缓存查询结果可能很棘手,因为您通常需要缓存所有 结果,而不仅仅是第一个“页面”值。这通常非常昂贵,并且具有超过缓存值(value)的高传输成本。

此外,您绝对会遇到缓存查询结果的新鲜度问题。当新记录出现时,它们不会出现在缓存列表中。使用仅实体缓存可以避免这种情况,因为 ID 列表始终是新鲜的,只有实体本身可能是陈旧的(但它有一种更简单的缓存过期方法)。

如果您担心实体过时,您不仅可以返回一个 ID,还可以返回一个“最后更新日期”,这样您就可以比较每个实体与缓存的新鲜度。

关于复杂查询的缓存策略/设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49009127/

相关文章:

python缓存库

node.js/LRU缓存包-max参数

javascript - Angular : centralised resource factory with promises

java - 绝地武士得到陈旧的数据

sorting - 排序redis缓存

javascript - 未在 Google Chrome 中清除缓存

c# - asp.net 核心数据保护 : An exception was thrown while deserializing the token

java - 使用新功能丰富类的设计模式

php - Symfony2 中的设计模式 : is EventDispatcher a Mediator or Event Aggregator?

redis - Kue JSON API 不返回任何数据 - KUE with AWS Redis