You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Redis优化NodeJS环境下GraphQL Server的API响应速度?

Redis Caching Implementation for Your Node.js GraphQL Server

Hey there! Let’s walk through exactly how to add Redis caching to your GraphQL server to slash those 10-15 second response times. Since your resolvers are calling external APIs, caching the results of those slow external calls is the perfect place to optimize.

Core Approach

We’ll check Redis for cached data before making an external API call. If the data exists in Redis, we return it immediately. If not, we fetch from the external API, store the result in Redis with an expiration time (to keep data fresh), then return it.

Step 1: Modify Your Resolvers to Use Caching

Your server already passes the Redis client via the context object, so we can use that directly in resolvers. Here’s a practical example tailored to your setup (adjust the field names and external API details to match your schema):

// Example resolver file (e.g., src/resolvers.js)
export const resolvers = {
  Query: {
    // Replace with your actual query field
    fetchUserDetails: async (_, { userId }, { client }) => {
      // Create a unique cache key based on the query and its arguments
      // This ensures different requests (e.g., different user IDs) get their own cache entries
      const cacheKey = `fetchUserDetails:${userId}`;

      try {
        // 1. Check Redis for cached data first
        const cachedData = await new Promise((resolve, reject) => {
          client.get(cacheKey, (err, data) => {
            if (err) {
              console.warn("Redis connection error, skipping cache:", err);
              resolve(null); // Fall back to external API if Redis is down
            } else {
              resolve(data);
            }
          });
        });

        if (cachedData) {
          console.log("Returning cached data for user:", userId);
          return JSON.parse(cachedData); // Parse since Redis stores strings
        }

        // 2. No cache found—call the external API
        console.log("Fetching fresh data for user:", userId);
        const externalResponse = await fetch(`https://your-external-api.com/users/${userId}`, {
          method: "GET",
          // Add any required headers (auth, content-type) here
        });
        const freshData = await externalResponse.json();

        // 3. Cache the result in Redis with a TTL (time-to-live)
        // Use `setex` to auto-expire the cache (3600 seconds = 1 hour in this example)
        // Adjust TTL based on how often your external data updates
        await new Promise((resolve, reject) => {
          client.setex(cacheKey, 3600, JSON.stringify(freshData), (err) => {
            if (err) reject(err);
            resolve();
          });
        });

        return freshData;
      } catch (err) {
        console.error("Error fetching user details:", err);
        throw new Error("Failed to retrieve user details");
      }
    },
  },
};

Step 2: Key Details to Customize

  • Unique Cache Keys: Always include query arguments in the cache key (like userId above) to avoid returning incorrect cached data for different requests. For complex arguments, use JSON.stringify(args) to create a consistent key.
  • TTL Configuration: The setex command’s second parameter is the expiration time in seconds. Use shorter TTLs (e.g., 60 seconds) for frequently updated data, and longer TTLs (e.g., 86400 seconds = 1 day) for static data.
  • Redis Fallback: If Redis goes down, the resolver will still work (it just skips caching and hits the external API directly), so your server stays functional.

Step 3: Add Cache Invalidation (For Mutations)

If your API has mutations that update external data, you’ll want to invalidate the corresponding cache entries to ensure users get fresh data after updates. Here’s an example:

Mutation: {
  updateUserProfile: async (_, { userId, newData }, { client }) => {
    // 1. Call external API to update the data
    const updateResponse = await fetch(`https://your-external-api.com/users/${userId}`, {
      method: "PUT",
      body: JSON.stringify(newData),
      headers: { "Content-Type": "application/json" },
    });
    const updatedData = await updateResponse.json();

    // 2. Delete the old cache entry for this user
    const cacheKey = `fetchUserDetails:${userId}`;
    await new Promise((resolve, reject) => {
      client.del(cacheKey, (err) => {
        if (err) reject(err);
        resolve();
      });
    });

    return updatedData;
  },
},

Step 4: Verify Your Setup

  • Test your query twice: The first request will hit the external API (you’ll see the "Fetching fresh data" log), and the second will return cached data instantly.
  • Use redis-cli to inspect your cache: Run KEYS * to see all cache keys, and GET fetchUserDetails:123 (replace with your key) to view the cached data.

内容的提问来源于stack exchange,提问作者Brunhilda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:52:58