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

NestJS中Redis缓存失效时禁用缓存避免服务崩溃

NestJS Redis缓存容错方案(Redis宕机时服务正常运行)

一、修改CacheModule配置:连接失败自动降级

将同步注册改为异步注册,在工厂函数中捕获Redis初始化错误,降级到内存缓存或直接禁用缓存:

import { CacheModule, Module } from "@nestjs/common";
import * as redisStore from "cache-manager-redis-store";
import { memoryStore } from "cache-manager";
// 若要完全禁用缓存,需先执行 npm install cache-manager-noop-store
// import { noopStore } from "cache-manager-noop-store";

@Module({
  imports: [
    CacheModule.registerAsync({
      isGlobal: true,
      useFactory: async () => {
        try {
          return {
            store: redisStore,
            host: process.env.REDIS_HOST,
            port: process.env.REDIS_PORT,
            password: process.env.REDIS_ACCESS_KEY,
            tls: { host: process.env.REDIS_HOST },
            ttl: 1800,
          };
        } catch (err) {
          console.warn("Redis连接失败,切换到内存缓存", err.message);
          // 若要完全禁用缓存,替换为 store: noopStore
          return { store: memoryStore, ttl: 1800 };
        }
      },
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

二、自定义容错拦截器:避免CacheInterceptor报错

默认CacheInterceptor在Redis故障时会抛出错误导致请求失败,自定义拦截器捕获错误后直接执行原请求逻辑:

import { CacheInterceptor, ExecutionContext, Injectable } from "@nestjs/common";
import { Observable, catchError } from "rxjs";

@Injectable()
export class FaultTolerantCacheInterceptor extends CacheInterceptor {
  intercept(context: ExecutionContext, call$: Observable<any>): Observable<any> {
    return super.intercept(context, call$).pipe(
      catchError((err) => {
        console.warn("缓存拦截器操作失败,跳过缓存", err.message);
        return call$;
      })
    );
  }
}

替换控制器中的拦截器:

import { Controller, Get, UseInterceptors } from "@nestjs/common";
import { FaultTolerantCacheInterceptor } from "./fault-tolerant-cache.interceptor";

@Controller()
@UseInterceptors(FaultTolerantCacheInterceptor)
export class AppController {
  @Get()
  findAll(): string[] {
    return [];
  }
}

三、封装cache.wrap:捕获缓存操作错误

直接使用cacheManager.wrap会在Redis故障时抛出错误,封装工具方法兜底业务逻辑:

创建缓存服务:

import { Inject, Injectable } from "@nestjs/common";
import { CACHE_MANAGER, Cache } from "cache-manager";

@Injectable()
export class CacheService {
  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

  async wrap<T>(key: string, fallback: () => Promise<T>): Promise<T> {
    try {
      return await this.cacheManager.wrap(key, fallback);
    } catch (err) {
      console.warn(`缓存key [${key}]操作失败,直接调用业务逻辑`, err.message);
      return fallback();
    }
  }
}

控制器中使用封装后的服务(修正原代码中code笔误为id):

import { Body, Controller, Post } from "@nestjs/common";
import { ItemsService } from "./items.service";
import { CacheService } from "./cache.service";

@Controller("items")
export class ItemsController {
  constructor(
    private itemsService: ItemsService,
    private cacheService: CacheService
  ) {}

  @Post("id")
  async getItemById(@Body("id") id: number) {
    return this.cacheService.wrap(`item-${id}`, () =>
      this.itemsService.getItem(id)
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 09:57:08