5

文档(https://www.apollographql.com/docs/apollo-server/features/data-sources.html#Using-Memcached-Redis-as-a-cache-storage-backend)显示如下代码:

const { RedisCache } = require('apollo-server-cache-redis');

const server = new ApolloServer({
  typeDefs,
  resolvers,
  cache: new RedisCache({
    host: 'redis-server',
    // Options are passed through to the Redis client
  }),
  dataSources: () => ({
    moviesAPI: new MoviesAPI(),
  }),
});

我想知道如何cache使用该密钥,考虑到缓存似乎实际上是自定义实现的MoviesAPI(),然后通过context.dataSources.moviesAPI.someFunc(). 例如,假设我想为 SQL 数据库实现自己的缓存。它看起来像

  cache: new RedisCache({
    host: 'redis-server',
  }),
  dataSources: () => ({
    SQL: new SQLCache(),
  }),
});

whereSQLCache有我自己的连接到RedisCache类似的功能:

  getCached(id, query, ttl) {
    const cacheKey = `sqlcache:${id}`;

    return redisCache.get(cacheKey).then(entry => {
      if (entry) {
        console.log('CACHE HIT!');
        return Promise.resolve(JSON.parse(entry));
      }
      console.log('CACHE MISS!');
      return query.then(rows => {
        if (rows) redisCache.set(cacheKey, JSON.stringify(rows), ttl);
        return Promise.resolve(rows);
      });
    });
  }

所以这意味着我拥有RedisCache关键ApolloServer cachedataSource实施。显然,RedisCache在实现中使用了dataSource,但是那个ApolloServer cache键到底是做什么的呢?

同样在客户端,示例大多显示使用InMemoryCache而不是 Redis 缓存。客户端 Apollo 缓存应该是与服务器缓存不同的缓存,还是应该RedisCache在两个地方都使用相同的缓存?

4

1 回答 1

8

据我所知,cache传递给的ApolloServer是严格在 a 的上下文中使用的RESTDataSource。从 REST 端点获取资源时,服务器将检查Cache-Control响应中的标头,如果存在,将适当地缓存资源。这意味着如果标头是max-age=86400,则响应将以 24 小时的 TTL 缓存,并且在缓存条目过期之前,将使用它而不是调用相同的 REST url。

这与您实现的缓存机制不同,因为您的代码缓存了来自数据库的响应。他们的意图是相同的,但他们使用不同的资源。您的代码有效复制 ApolloServercache已经做的唯一方法是,如果您DataSource为 REST 端点编写了类似的代码。

虽然这两种缓存都减少了处理 GraphQL 响应所需的时间(从缓存中获取明显快于从数据库中获取),但客户端缓存减少了必须向服务器发出的请求数量。最值得注意的是,它InMemoryCache允许您在站点的不同位置(如 React 中的不同组件)重用一个查询,而只获取一次查询。

因为客户端缓存是规范化的,这也意味着如果通过一个查询获取资源时已经缓存了资源,您可以避免在另一个查询请求它时重新获取它。例如,如果您使用一个查询获取用户列表,然后使用另一个查询获取用户,则您的客户端可以配置为在缓存中查找用户,而不是进行第二个查询。

需要注意的是,虽然服务器端缓存的资源通常具有 TTL,但InMemoryCache实际上没有。相反,它使用“获取策略”来确定单个查询的行为。例如,这使您可以有一个始终从服务器获取的查询,而不管缓存中有什么。

希望这有助于说明服务器端和客户端缓存都是有用的,但方式却截然不同。

于 2018-11-18T14:34:43.543 回答