【问题标题】:Caching Strategy/Design Pattern for complex queries复杂查询的缓存策略/设计模式
【发布时间】:2018-08-07 03:02:36
【问题描述】:

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

SELECT * FROM [Entities] WHERE PrimaryKeyCol = @p1

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

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

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    如果您担心实体的陈旧性,您不仅可以返回一个 ID,还可以返回一个“上次更新日期”,让您可以将每个实体的新鲜度与缓存进行比较。

    【讨论】:

    • 感谢 Rob 的输入。当我写上面的原件时,我还没有想到其他一些事情。 1,如果我们的非规范化和分区策略正确,使用 Cosmos 将比 SQL 快几个数量级。 2. 这个 API 可以很容易地放在 Azure API 管理服务之后,这将允许我们进行请求/响应缓存。鉴于这两个事实,我想我会采纳您的建议并放弃 Redis 方法。干杯。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    相关资源
    最近更新 更多