[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache":1659,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache":1685},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":1655,"stem":1656,"id":1657,"extension":1658},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache","缓存","@nestjs\u002Fcache-manager 统一缓存 API，存储实现可插拔。","技能小册",[12,13],"nestjs","cache","2025-07-04",false,{"type":17,"value":18,"toc":1644},"minimark",[19,22,30,36,40,50,78,93,310,328,332,337,340,354,364,636,640,651,970,974,981,1125,1129,1146,1250,1254,1257,1405,1408,1471,1474,1580,1583,1587,1590,1640],[20,21,8],"h1",{"id":8},[23,24,25,29],"p",{},[26,27,28],"code",{},"@nestjs\u002Fcache-manager"," 统一缓存 API，存储实现可插拔。",[23,31,32,33,35],{},"NestJS 的缓存模块是通过 ",[26,34,28],{}," 包来实现的，它为应用带来了一个简单统一的 API，底层支持多种性能出色的缓存存储方案，并可以灵活配置。",[37,38,39],"h3",{"id":39},"模块导入与基础配置",[23,41,42,43,45,46,49],{},"要开始使用缓存，首先需要安装 ",[26,44,28],{}," 核心包和 ",[26,47,48],{},"cache-manager"," 存储驱动：",[51,52,57],"pre",{"className":53,"code":54,"language":55,"meta":56,"style":56},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","npm install @nestjs\u002Fcache-manager cache-manager\n","bash","",[26,58,59],{"__ignoreMap":56},[60,61,64,68,72,75],"span",{"class":62,"line":63},"line",1,[60,65,67],{"class":66},"sbgvK","npm",[60,69,71],{"class":70},"s_sjI"," install",[60,73,74],{"class":70}," @nestjs\u002Fcache-manager",[60,76,77],{"class":70}," cache-manager\n",[23,79,80,81,84,85,88,89,92],{},"安装完成后，在模块（例如 ",[26,82,83],{},"AppModule","）中通过 ",[26,86,87],{},".register()"," 方法导入并配置 ",[26,90,91],{},"CacheModule","，最基础的内存缓存开启方式如下：",[51,94,98],{"className":95,"code":96,"language":97,"meta":56,"style":56},"language-typescript shiki shiki-themes material-theme-lighter github-light github-dark","\u002F\u002F app.module.ts\nimport { Module } from \"@nestjs\u002Fcommon\";\nimport { CacheModule } from \"@nestjs\u002Fcache-manager\";\n\n@Module({\n  imports: [\n    CacheModule.register({\n      ttl: 60000, \u002F\u002F 设置全局缓存过期时间为 60 秒（单位：毫秒）\n      max: 100, \u002F\u002F 设置内存缓存中最大存储的项数为 100\n      isGlobal: true, \u002F\u002F 设为全局，避免在每个模块重复导入\n    }),\n  ],\n})\nexport class AppModule {}\n","typescript",[26,99,100,106,140,162,169,185,198,214,232,248,265,277,285,294],{"__ignoreMap":56},[60,101,102],{"class":62,"line":63},[60,103,105],{"class":104},"sutJx","\u002F\u002F app.module.ts\n",[60,107,109,113,117,121,124,127,131,134,137],{"class":62,"line":108},2,[60,110,112],{"class":111},"sVHd0","import",[60,114,116],{"class":115},"sP7_E"," {",[60,118,120],{"class":119},"su5hD"," Module",[60,122,123],{"class":115}," }",[60,125,126],{"class":111}," from",[60,128,130],{"class":129},"sjJ54"," \"",[60,132,133],{"class":70},"@nestjs\u002Fcommon",[60,135,136],{"class":129},"\"",[60,138,139],{"class":115},";\n",[60,141,143,145,147,150,152,154,156,158,160],{"class":62,"line":142},3,[60,144,112],{"class":111},[60,146,116],{"class":115},[60,148,149],{"class":119}," CacheModule",[60,151,123],{"class":115},[60,153,126],{"class":111},[60,155,130],{"class":129},[60,157,28],{"class":70},[60,159,136],{"class":129},[60,161,139],{"class":115},[60,163,165],{"class":62,"line":164},4,[60,166,168],{"emptyLinePlaceholder":167},true,"\n",[60,170,172,175,179,182],{"class":62,"line":171},5,[60,173,174],{"class":115},"@",[60,176,178],{"class":177},"sGLFI","Module",[60,180,181],{"class":119},"(",[60,183,184],{"class":115},"{\n",[60,186,188,192,195],{"class":62,"line":187},6,[60,189,191],{"class":190},"skxfh","  imports",[60,193,194],{"class":115},":",[60,196,197],{"class":119}," [\n",[60,199,201,204,207,210,212],{"class":62,"line":200},7,[60,202,203],{"class":119},"    CacheModule",[60,205,206],{"class":115},".",[60,208,209],{"class":177},"register",[60,211,181],{"class":119},[60,213,184],{"class":115},[60,215,217,220,222,226,229],{"class":62,"line":216},8,[60,218,219],{"class":190},"      ttl",[60,221,194],{"class":115},[60,223,225],{"class":224},"srdBf"," 60000",[60,227,228],{"class":115},",",[60,230,231],{"class":104}," \u002F\u002F 设置全局缓存过期时间为 60 秒（单位：毫秒）\n",[60,233,235,238,240,243,245],{"class":62,"line":234},9,[60,236,237],{"class":190},"      max",[60,239,194],{"class":115},[60,241,242],{"class":224}," 100",[60,244,228],{"class":115},[60,246,247],{"class":104}," \u002F\u002F 设置内存缓存中最大存储的项数为 100\n",[60,249,251,254,256,260,262],{"class":62,"line":250},10,[60,252,253],{"class":190},"      isGlobal",[60,255,194],{"class":115},[60,257,259],{"class":258},"syTEX"," true",[60,261,228],{"class":115},[60,263,264],{"class":104}," \u002F\u002F 设为全局，避免在每个模块重复导入\n",[60,266,268,271,274],{"class":62,"line":267},11,[60,269,270],{"class":115},"    }",[60,272,273],{"class":119},")",[60,275,276],{"class":115},",\n",[60,278,280,283],{"class":62,"line":279},12,[60,281,282],{"class":119},"  ]",[60,284,276],{"class":115},[60,286,288,291],{"class":62,"line":287},13,[60,289,290],{"class":115},"}",[60,292,293],{"class":119},")\n",[60,295,297,300,304,307],{"class":62,"line":296},14,[60,298,299],{"class":111},"export",[60,301,303],{"class":302},"sbsja"," class",[60,305,306],{"class":66}," AppModule",[60,308,309],{"class":115}," {}\n",[23,311,312,316,317,319,320,323,324,327],{},[313,314,315],"strong",{},"⚠️ 特别提醒","：在使用 ",[26,318,48],{}," v5 或更高版本时，",[26,321,322],{},"ttl"," 的单位是",[313,325,326],{},"毫秒"," (milliseconds), 而旧版 v4 使用的是秒 (seconds)。需要仔细核对所使用的库版本。",[37,329,331],{"id":330},"存储引擎内存-vs-redis","💾 存储引擎：内存 vs. Redis",[23,333,334,336],{},[26,335,28],{}," 默认提供内存缓存，它可以直接将数据存储在应用进程中，适用于单机或中小规模的场景。但对于需要跨实例共享缓存的分布式系统，则必须选择像 Redis 这样的集中式存储。",[23,338,339],{},"使用 Redis 时，需要额外安装驱动包并调整配置：",[51,341,343],{"className":53,"code":342,"language":55,"meta":56,"style":56},"npm install cache-manager-redis-yet\n",[26,344,345],{"__ignoreMap":56},[60,346,347,349,351],{"class":62,"line":63},[60,348,67],{"class":66},[60,350,71],{"class":70},[60,352,353],{"class":70}," cache-manager-redis-yet\n",[23,355,356,357,359,360,363],{},"然后在 ",[26,358,91],{}," 中配置 ",[26,361,362],{},"store"," 和连接参数：",[51,365,367],{"className":95,"code":366,"language":97,"meta":56,"style":56},"\u002F\u002F app.module.ts\nimport { Module } from \"@nestjs\u002Fcommon\";\nimport { CacheModule } from \"@nestjs\u002Fcache-manager\";\nimport { redisStore } from \"cache-manager-redis-yet\";\n\n@Module({\n  imports: [\n    CacheModule.registerAsync({\n      useFactory: async () => ({\n        store: await redisStore({\n          socket: {\n            host: \"localhost\",\n            port: 6379,\n          },\n          password: \"your-password\",\n          ttl: 60000, \u002F\u002F 基于 Redis 的 TTL\n        }),\n      }),\n    }),\n  ],\n})\nexport class AppModule {}\n",[26,368,369,373,393,413,435,439,449,457,470,491,507,517,533,545,550,567,582,592,602,611,618,625],{"__ignoreMap":56},[60,370,371],{"class":62,"line":63},[60,372,105],{"class":104},[60,374,375,377,379,381,383,385,387,389,391],{"class":62,"line":108},[60,376,112],{"class":111},[60,378,116],{"class":115},[60,380,120],{"class":119},[60,382,123],{"class":115},[60,384,126],{"class":111},[60,386,130],{"class":129},[60,388,133],{"class":70},[60,390,136],{"class":129},[60,392,139],{"class":115},[60,394,395,397,399,401,403,405,407,409,411],{"class":62,"line":142},[60,396,112],{"class":111},[60,398,116],{"class":115},[60,400,149],{"class":119},[60,402,123],{"class":115},[60,404,126],{"class":111},[60,406,130],{"class":129},[60,408,28],{"class":70},[60,410,136],{"class":129},[60,412,139],{"class":115},[60,414,415,417,419,422,424,426,428,431,433],{"class":62,"line":164},[60,416,112],{"class":111},[60,418,116],{"class":115},[60,420,421],{"class":119}," redisStore",[60,423,123],{"class":115},[60,425,126],{"class":111},[60,427,130],{"class":129},[60,429,430],{"class":70},"cache-manager-redis-yet",[60,432,136],{"class":129},[60,434,139],{"class":115},[60,436,437],{"class":62,"line":171},[60,438,168],{"emptyLinePlaceholder":167},[60,440,441,443,445,447],{"class":62,"line":187},[60,442,174],{"class":115},[60,444,178],{"class":177},[60,446,181],{"class":119},[60,448,184],{"class":115},[60,450,451,453,455],{"class":62,"line":200},[60,452,191],{"class":190},[60,454,194],{"class":115},[60,456,197],{"class":119},[60,458,459,461,463,466,468],{"class":62,"line":216},[60,460,203],{"class":119},[60,462,206],{"class":115},[60,464,465],{"class":177},"registerAsync",[60,467,181],{"class":119},[60,469,184],{"class":115},[60,471,472,475,477,480,483,486,489],{"class":62,"line":234},[60,473,474],{"class":177},"      useFactory",[60,476,194],{"class":115},[60,478,479],{"class":302}," async",[60,481,482],{"class":115}," ()",[60,484,485],{"class":302}," =>",[60,487,488],{"class":119}," (",[60,490,184],{"class":115},[60,492,493,496,498,501,503,505],{"class":62,"line":250},[60,494,495],{"class":190},"        store",[60,497,194],{"class":115},[60,499,500],{"class":111}," await",[60,502,421],{"class":177},[60,504,181],{"class":119},[60,506,184],{"class":115},[60,508,509,512,514],{"class":62,"line":267},[60,510,511],{"class":190},"          socket",[60,513,194],{"class":115},[60,515,516],{"class":115}," {\n",[60,518,519,522,524,526,529,531],{"class":62,"line":279},[60,520,521],{"class":190},"            host",[60,523,194],{"class":115},[60,525,130],{"class":129},[60,527,528],{"class":70},"localhost",[60,530,136],{"class":129},[60,532,276],{"class":115},[60,534,535,538,540,543],{"class":62,"line":287},[60,536,537],{"class":190},"            port",[60,539,194],{"class":115},[60,541,542],{"class":224}," 6379",[60,544,276],{"class":115},[60,546,547],{"class":62,"line":296},[60,548,549],{"class":115},"          },\n",[60,551,553,556,558,560,563,565],{"class":62,"line":552},15,[60,554,555],{"class":190},"          password",[60,557,194],{"class":115},[60,559,130],{"class":129},[60,561,562],{"class":70},"your-password",[60,564,136],{"class":129},[60,566,276],{"class":115},[60,568,570,573,575,577,579],{"class":62,"line":569},16,[60,571,572],{"class":190},"          ttl",[60,574,194],{"class":115},[60,576,225],{"class":224},[60,578,228],{"class":115},[60,580,581],{"class":104}," \u002F\u002F 基于 Redis 的 TTL\n",[60,583,585,588,590],{"class":62,"line":584},17,[60,586,587],{"class":115},"        }",[60,589,273],{"class":119},[60,591,276],{"class":115},[60,593,595,598,600],{"class":62,"line":594},18,[60,596,597],{"class":115},"      }",[60,599,273],{"class":119},[60,601,276],{"class":115},[60,603,605,607,609],{"class":62,"line":604},19,[60,606,270],{"class":115},[60,608,273],{"class":119},[60,610,276],{"class":115},[60,612,614,616],{"class":62,"line":613},20,[60,615,282],{"class":119},[60,617,276],{"class":115},[60,619,621,623],{"class":62,"line":620},21,[60,622,290],{"class":115},[60,624,293],{"class":119},[60,626,628,630,632,634],{"class":62,"line":627},22,[60,629,299],{"class":111},[60,631,303],{"class":302},[60,633,306],{"class":66},[60,635,309],{"class":115},[37,637,639],{"id":638},"️-与缓存实例交互","🛠️ 与缓存实例交互",[23,641,642,643,646,647,650],{},"在某些复杂场景下，你可能需要直接操作缓存。通过 ",[26,644,645],{},"CACHE_MANAGER"," 这个 token 就可以注入 ",[26,648,649],{},"Cache"," 实例，进而对缓存进行精细化的控制。",[51,652,654],{"className":95,"code":653,"language":97,"meta":56,"style":56},"\u002F\u002F your.service.ts\nimport { Injectable, Inject } from \"@nestjs\u002Fcommon\";\nimport { CACHE_MANAGER } from \"@nestjs\u002Fcache-manager\";\nimport { Cache } from \"cache-manager\";\n\n@Injectable()\nexport class YourService {\n  constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}\n\n  async getValue(key: string) {\n    \u002F\u002F 获取缓存，若不存在则返回 null\n    const value = await this.cacheManager.get(key);\n    \u002F\u002F 手动设置缓存，第三个参数可指定该键的 TTL（单位：毫秒）\n    await this.cacheManager.set(key, { value: \"cached data\" }, 1000);\n    \u002F\u002F 删除单个键\n    await this.cacheManager.del(key);\n    \u002F\u002F 清空整个缓存（请谨慎使用）\n    await this.cacheManager.reset();\n  }\n}\n",[26,655,656,661,687,708,729,733,743,754,789,793,817,822,857,862,907,912,935,940,960,965],{"__ignoreMap":56},[60,657,658],{"class":62,"line":63},[60,659,660],{"class":104},"\u002F\u002F your.service.ts\n",[60,662,663,665,667,670,672,675,677,679,681,683,685],{"class":62,"line":108},[60,664,112],{"class":111},[60,666,116],{"class":115},[60,668,669],{"class":119}," Injectable",[60,671,228],{"class":115},[60,673,674],{"class":119}," Inject",[60,676,123],{"class":115},[60,678,126],{"class":111},[60,680,130],{"class":129},[60,682,133],{"class":70},[60,684,136],{"class":129},[60,686,139],{"class":115},[60,688,689,691,693,696,698,700,702,704,706],{"class":62,"line":142},[60,690,112],{"class":111},[60,692,116],{"class":115},[60,694,695],{"class":119}," CACHE_MANAGER",[60,697,123],{"class":115},[60,699,126],{"class":111},[60,701,130],{"class":129},[60,703,28],{"class":70},[60,705,136],{"class":129},[60,707,139],{"class":115},[60,709,710,712,714,717,719,721,723,725,727],{"class":62,"line":164},[60,711,112],{"class":111},[60,713,116],{"class":115},[60,715,716],{"class":119}," Cache",[60,718,123],{"class":115},[60,720,126],{"class":111},[60,722,130],{"class":129},[60,724,48],{"class":70},[60,726,136],{"class":129},[60,728,139],{"class":115},[60,730,731],{"class":62,"line":171},[60,732,168],{"emptyLinePlaceholder":167},[60,734,735,737,740],{"class":62,"line":187},[60,736,174],{"class":115},[60,738,739],{"class":177},"Injectable",[60,741,742],{"class":119},"()\n",[60,744,745,747,749,752],{"class":62,"line":200},[60,746,299],{"class":111},[60,748,303],{"class":302},[60,750,751],{"class":66}," YourService",[60,753,516],{"class":115},[60,755,756,759,762,765,767,770,773,776,780,783,785,787],{"class":62,"line":216},[60,757,758],{"class":302},"  constructor",[60,760,761],{"class":115},"(@",[60,763,764],{"class":177},"Inject",[60,766,181],{"class":119},[60,768,645],{"class":769},"s_hVV",[60,771,772],{"class":119},") ",[60,774,775],{"class":302},"private",[60,777,779],{"class":778},"s99_P"," cacheManager",[60,781,194],{"class":782},"smGrS",[60,784,716],{"class":66},[60,786,273],{"class":115},[60,788,309],{"class":115},[60,790,791],{"class":62,"line":234},[60,792,168],{"emptyLinePlaceholder":167},[60,794,795,798,802,804,807,809,813,815],{"class":62,"line":250},[60,796,797],{"class":302},"  async",[60,799,801],{"class":800},"sVXei"," getValue",[60,803,181],{"class":115},[60,805,806],{"class":778},"key",[60,808,194],{"class":782},[60,810,812],{"class":811},"sZMiF"," string",[60,814,273],{"class":115},[60,816,516],{"class":115},[60,818,819],{"class":62,"line":267},[60,820,821],{"class":104},"    \u002F\u002F 获取缓存，若不存在则返回 null\n",[60,823,824,827,830,833,835,839,841,844,846,849,851,853,855],{"class":62,"line":279},[60,825,826],{"class":302},"    const",[60,828,829],{"class":769}," value",[60,831,832],{"class":782}," =",[60,834,500],{"class":111},[60,836,838],{"class":837},"s39Yj"," this",[60,840,206],{"class":115},[60,842,843],{"class":119},"cacheManager",[60,845,206],{"class":115},[60,847,848],{"class":177},"get",[60,850,181],{"class":190},[60,852,806],{"class":119},[60,854,273],{"class":190},[60,856,139],{"class":115},[60,858,859],{"class":62,"line":287},[60,860,861],{"class":104},"    \u002F\u002F 手动设置缓存，第三个参数可指定该键的 TTL（单位：毫秒）\n",[60,863,864,867,869,871,873,875,878,880,882,884,886,888,890,892,895,897,900,903,905],{"class":62,"line":296},[60,865,866],{"class":111},"    await",[60,868,838],{"class":837},[60,870,206],{"class":115},[60,872,843],{"class":119},[60,874,206],{"class":115},[60,876,877],{"class":177},"set",[60,879,181],{"class":190},[60,881,806],{"class":119},[60,883,228],{"class":115},[60,885,116],{"class":115},[60,887,829],{"class":190},[60,889,194],{"class":115},[60,891,130],{"class":129},[60,893,894],{"class":70},"cached data",[60,896,136],{"class":129},[60,898,899],{"class":115}," },",[60,901,902],{"class":224}," 1000",[60,904,273],{"class":190},[60,906,139],{"class":115},[60,908,909],{"class":62,"line":552},[60,910,911],{"class":104},"    \u002F\u002F 删除单个键\n",[60,913,914,916,918,920,922,924,927,929,931,933],{"class":62,"line":569},[60,915,866],{"class":111},[60,917,838],{"class":837},[60,919,206],{"class":115},[60,921,843],{"class":119},[60,923,206],{"class":115},[60,925,926],{"class":177},"del",[60,928,181],{"class":190},[60,930,806],{"class":119},[60,932,273],{"class":190},[60,934,139],{"class":115},[60,936,937],{"class":62,"line":584},[60,938,939],{"class":104},"    \u002F\u002F 清空整个缓存（请谨慎使用）\n",[60,941,942,944,946,948,950,952,955,958],{"class":62,"line":594},[60,943,866],{"class":111},[60,945,838],{"class":837},[60,947,206],{"class":115},[60,949,843],{"class":119},[60,951,206],{"class":115},[60,953,954],{"class":177},"reset",[60,956,957],{"class":190},"()",[60,959,139],{"class":115},[60,961,962],{"class":62,"line":604},[60,963,964],{"class":115},"  }\n",[60,966,967],{"class":62,"line":613},[60,968,969],{"class":115},"}\n",[37,971,973],{"id":972},"自动缓存响应-cacheinterceptor","🧩 自动缓存响应 (CacheInterceptor)",[23,975,976,977,980],{},"若只需对 GET 请求进行缓存，使用 ",[26,978,979],{},"CacheInterceptor"," 是最简洁的方案。它将自动拦截响应并将其存入缓存。你可以将其应用到控制器层（作用于所有路由）或方法层。",[51,982,984],{"className":95,"code":983,"language":97,"meta":56,"style":56},"\u002F\u002F app.controller.ts\nimport { Controller, Get, UseInterceptors } from \"@nestjs\u002Fcommon\";\nimport { CacheInterceptor } from \"@nestjs\u002Fcache-manager\";\n\n@Controller()\n@UseInterceptors(CacheInterceptor)\nexport class AppController {\n  @Get()\n  findAll(): string[] {\n    return []; \u002F\u002F 此响应将被自动缓存\n  }\n}\n",[26,985,986,991,1022,1043,1047,1056,1066,1077,1087,1103,1117,1121],{"__ignoreMap":56},[60,987,988],{"class":62,"line":63},[60,989,990],{"class":104},"\u002F\u002F app.controller.ts\n",[60,992,993,995,997,1000,1002,1005,1007,1010,1012,1014,1016,1018,1020],{"class":62,"line":108},[60,994,112],{"class":111},[60,996,116],{"class":115},[60,998,999],{"class":119}," Controller",[60,1001,228],{"class":115},[60,1003,1004],{"class":119}," Get",[60,1006,228],{"class":115},[60,1008,1009],{"class":119}," UseInterceptors",[60,1011,123],{"class":115},[60,1013,126],{"class":111},[60,1015,130],{"class":129},[60,1017,133],{"class":70},[60,1019,136],{"class":129},[60,1021,139],{"class":115},[60,1023,1024,1026,1028,1031,1033,1035,1037,1039,1041],{"class":62,"line":142},[60,1025,112],{"class":111},[60,1027,116],{"class":115},[60,1029,1030],{"class":119}," CacheInterceptor",[60,1032,123],{"class":115},[60,1034,126],{"class":111},[60,1036,130],{"class":129},[60,1038,28],{"class":70},[60,1040,136],{"class":129},[60,1042,139],{"class":115},[60,1044,1045],{"class":62,"line":164},[60,1046,168],{"emptyLinePlaceholder":167},[60,1048,1049,1051,1054],{"class":62,"line":171},[60,1050,174],{"class":115},[60,1052,1053],{"class":177},"Controller",[60,1055,742],{"class":119},[60,1057,1058,1060,1063],{"class":62,"line":187},[60,1059,174],{"class":115},[60,1061,1062],{"class":177},"UseInterceptors",[60,1064,1065],{"class":119},"(CacheInterceptor)\n",[60,1067,1068,1070,1072,1075],{"class":62,"line":200},[60,1069,299],{"class":111},[60,1071,303],{"class":302},[60,1073,1074],{"class":66}," AppController",[60,1076,516],{"class":115},[60,1078,1079,1082,1085],{"class":62,"line":216},[60,1080,1081],{"class":115},"  @",[60,1083,1084],{"class":177},"Get",[60,1086,742],{"class":119},[60,1088,1089,1092,1094,1096,1098,1101],{"class":62,"line":234},[60,1090,1091],{"class":800},"  findAll",[60,1093,957],{"class":115},[60,1095,194],{"class":782},[60,1097,812],{"class":811},[60,1099,1100],{"class":119},"[] ",[60,1102,184],{"class":115},[60,1104,1105,1108,1111,1114],{"class":62,"line":250},[60,1106,1107],{"class":111},"    return",[60,1109,1110],{"class":190}," []",[60,1112,1113],{"class":115},";",[60,1115,1116],{"class":104}," \u002F\u002F 此响应将被自动缓存\n",[60,1118,1119],{"class":62,"line":267},[60,1120,964],{"class":115},[60,1122,1123],{"class":62,"line":279},[60,1124,969],{"class":115},[37,1126,1128],{"id":1127},"自定义缓存键-cachekey-与-ttl-cachettl","🎨 自定义缓存键 (CacheKey) 与 TTL (CacheTTL)",[23,1130,1131,1133,1134,1137,1138,1141,1142,1145],{},[26,1132,979],{}," 默认会根据路由生成缓存键，例如 ",[26,1135,1136],{},"GET \u002Fusers","。如果需要更精细的控制，可以使用 ",[26,1139,1140],{},"@CacheKey()"," 和 ",[26,1143,1144],{},"@CacheTTL()"," 装饰器。",[51,1147,1149],{"className":95,"code":1148,"language":97,"meta":56,"style":56},"import { CacheKey, CacheTTL } from '@nestjs\u002Fcache-manager';\n\n@Get()\n@CacheKey('custom_key_for_findAll')\n@CacheTTL(120000)  \u002F\u002F 覆盖全局设置，将此接口的缓存时间设为 120 秒\nfindAll(): string[] {\n  return [];\n}\n",[26,1150,1151,1179,1183,1191,1209,1227,1237,1246],{"__ignoreMap":56},[60,1152,1153,1155,1157,1160,1162,1165,1167,1169,1172,1174,1177],{"class":62,"line":63},[60,1154,112],{"class":111},[60,1156,116],{"class":115},[60,1158,1159],{"class":119}," CacheKey",[60,1161,228],{"class":115},[60,1163,1164],{"class":119}," CacheTTL",[60,1166,123],{"class":115},[60,1168,126],{"class":111},[60,1170,1171],{"class":129}," '",[60,1173,28],{"class":70},[60,1175,1176],{"class":129},"'",[60,1178,139],{"class":115},[60,1180,1181],{"class":62,"line":108},[60,1182,168],{"emptyLinePlaceholder":167},[60,1184,1185,1187,1189],{"class":62,"line":142},[60,1186,174],{"class":115},[60,1188,1084],{"class":177},[60,1190,742],{"class":119},[60,1192,1193,1195,1198,1200,1202,1205,1207],{"class":62,"line":164},[60,1194,174],{"class":115},[60,1196,1197],{"class":177},"CacheKey",[60,1199,181],{"class":119},[60,1201,1176],{"class":129},[60,1203,1204],{"class":70},"custom_key_for_findAll",[60,1206,1176],{"class":129},[60,1208,293],{"class":119},[60,1210,1211,1213,1216,1218,1221,1224],{"class":62,"line":171},[60,1212,174],{"class":115},[60,1214,1215],{"class":177},"CacheTTL",[60,1217,181],{"class":119},[60,1219,1220],{"class":224},"120000",[60,1222,1223],{"class":119},")  ",[60,1225,1226],{"class":104},"\u002F\u002F 覆盖全局设置，将此接口的缓存时间设为 120 秒\n",[60,1228,1229,1232,1235],{"class":62,"line":187},[60,1230,1231],{"class":177},"findAll",[60,1233,1234],{"class":119},"(): string[] ",[60,1236,184],{"class":115},[60,1238,1239,1242,1244],{"class":62,"line":200},[60,1240,1241],{"class":111},"  return",[60,1243,1110],{"class":190},[60,1245,139],{"class":115},[60,1247,1248],{"class":62,"line":216},[60,1249,969],{"class":115},[37,1251,1253],{"id":1252},"全局缓存配置","🌐 全局缓存配置",[23,1255,1256],{},"如果你希望缓存拦截器默认作用于所有路由，可以在模块配置中将其声明为全局拦截器，但也需要注意对 WebSocket 或非 GET 请求等场景的处理。",[51,1258,1260],{"className":95,"code":1259,"language":97,"meta":56,"style":56},"\u002F\u002F app.module.ts\nimport { Module } from \"@nestjs\u002Fcommon\";\nimport { APP_INTERCEPTOR } from \"@nestjs\u002Fcore\";\nimport { CacheInterceptor } from \"@nestjs\u002Fcache-manager\";\n\n@Module({\n  providers: [\n    {\n      provide: APP_INTERCEPTOR,\n      useClass: CacheInterceptor,\n    },\n  ],\n})\nexport class AppModule {}\n",[26,1261,1262,1266,1286,1308,1328,1332,1342,1351,1356,1367,1378,1383,1389,1395],{"__ignoreMap":56},[60,1263,1264],{"class":62,"line":63},[60,1265,105],{"class":104},[60,1267,1268,1270,1272,1274,1276,1278,1280,1282,1284],{"class":62,"line":108},[60,1269,112],{"class":111},[60,1271,116],{"class":115},[60,1273,120],{"class":119},[60,1275,123],{"class":115},[60,1277,126],{"class":111},[60,1279,130],{"class":129},[60,1281,133],{"class":70},[60,1283,136],{"class":129},[60,1285,139],{"class":115},[60,1287,1288,1290,1292,1295,1297,1299,1301,1304,1306],{"class":62,"line":142},[60,1289,112],{"class":111},[60,1291,116],{"class":115},[60,1293,1294],{"class":119}," APP_INTERCEPTOR",[60,1296,123],{"class":115},[60,1298,126],{"class":111},[60,1300,130],{"class":129},[60,1302,1303],{"class":70},"@nestjs\u002Fcore",[60,1305,136],{"class":129},[60,1307,139],{"class":115},[60,1309,1310,1312,1314,1316,1318,1320,1322,1324,1326],{"class":62,"line":164},[60,1311,112],{"class":111},[60,1313,116],{"class":115},[60,1315,1030],{"class":119},[60,1317,123],{"class":115},[60,1319,126],{"class":111},[60,1321,130],{"class":129},[60,1323,28],{"class":70},[60,1325,136],{"class":129},[60,1327,139],{"class":115},[60,1329,1330],{"class":62,"line":171},[60,1331,168],{"emptyLinePlaceholder":167},[60,1333,1334,1336,1338,1340],{"class":62,"line":187},[60,1335,174],{"class":115},[60,1337,178],{"class":177},[60,1339,181],{"class":119},[60,1341,184],{"class":115},[60,1343,1344,1347,1349],{"class":62,"line":200},[60,1345,1346],{"class":190},"  providers",[60,1348,194],{"class":115},[60,1350,197],{"class":119},[60,1352,1353],{"class":62,"line":216},[60,1354,1355],{"class":115},"    {\n",[60,1357,1358,1361,1363,1365],{"class":62,"line":234},[60,1359,1360],{"class":190},"      provide",[60,1362,194],{"class":115},[60,1364,1294],{"class":769},[60,1366,276],{"class":115},[60,1368,1369,1372,1374,1376],{"class":62,"line":250},[60,1370,1371],{"class":190},"      useClass",[60,1373,194],{"class":115},[60,1375,1030],{"class":119},[60,1377,276],{"class":115},[60,1379,1380],{"class":62,"line":267},[60,1381,1382],{"class":115},"    },\n",[60,1384,1385,1387],{"class":62,"line":279},[60,1386,282],{"class":119},[60,1388,276],{"class":115},[60,1390,1391,1393],{"class":62,"line":287},[60,1392,290],{"class":115},[60,1394,293],{"class":119},[60,1396,1397,1399,1401,1403],{"class":62,"line":296},[60,1398,299],{"class":111},[60,1400,303],{"class":302},[60,1402,306],{"class":66},[60,1404,309],{"class":115},[37,1406,1407],{"id":1407},"高级用法与最佳实践",[1409,1410,1411,1433,1445],"ol",{},[1412,1413,1414,1417,1418,1421,1422,1421,1425,1428,1429,1432],"li",{},[313,1415,1416],{},"缓存一致性","：当数据变更（如数据库的增、删、改操作）时，确保同时删除或更新对应的缓存。一种常见的模式是在 ",[26,1419,1420],{},"@Put()",", ",[26,1423,1424],{},"@Post()",[26,1426,1427],{},"@Delete()"," 等会修改数据的操作中，调用 ",[26,1430,1431],{},"this.cacheManager.del(key)","。",[1412,1434,1435,1438,1439,1442,1443,1432],{},[313,1436,1437],{},"访问控制","：避免在需要验证用户权限、需要返回动态内容（如需要 ",[26,1440,1441],{},"@Res()"," 直接操作响应）、或 GraphQL 解析器等场景中使用 ",[26,1444,979],{},[1412,1446,1447,1450,1451,1458,1459,1462,1463,1466,1467,1470],{},[313,1448,1449],{},"数据类型限制","：内存缓存只能存储符合 ",[1452,1453,1457],"a",{"href":1454,"rel":1455},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FWeb_Workers_API\u002FStructured_clone_algorithm#javascript_types",[1456],"nofollow","结构化克隆算法"," 支持的类型，如基本类型和普通对象。这意味着像 ",[26,1460,1461],{},"Date"," 对象、",[26,1464,1465],{},"Set","、",[26,1468,1469],{},"Map"," 等高级对象的缓存可能会遇到问题。",[37,1472,1473],{"id":1473},"总结",[1475,1476,1477,1491],"table",{},[1478,1479,1480],"thead",{},[1481,1482,1483,1488],"tr",{},[1484,1485,1487],"th",{"align":1486},"left","核心概念",[1484,1489,1490],{"align":1486},"实现关键点",[1492,1493,1494,1513,1526,1540,1554,1570],"tbody",{},[1481,1495,1496,1502],{},[1497,1498,1499],"td",{"align":1486},[313,1500,1501],{},"模块注册",[1497,1503,1504,1505,1508,1509,1512],{"align":1486},"使用 ",[26,1506,1507],{},"CacheModule.register()"," 进行基础配置；使用 ",[26,1510,1511],{},"CacheModule.registerAsync()"," 实现更灵活的动态配置。",[1481,1514,1515,1520],{},[1497,1516,1517],{"align":1486},[313,1518,1519],{},"存储选择",[1497,1521,1522,1523,1525],{"align":1486},"默认内存，适合开发；上生产或分布式场景需用 Redis，推荐 ",[26,1524,430],{}," 驱动。",[1481,1527,1528,1533],{},[1497,1529,1530],{"align":1486},[313,1531,1532],{},"自动缓存",[1497,1534,1535,1536,1539],{"align":1486},"通过 ",[26,1537,1538],{},"@UseInterceptors(CacheInterceptor)"," 实现，简单高效。",[1481,1541,1542,1547],{},[1497,1543,1544],{"align":1486},[313,1545,1546],{},"精细控制",[1497,1548,1535,1549,1141,1551,1553],{"align":1486},[26,1550,1140],{},[26,1552,1144],{}," 自定义键值与过期时间，满足特殊场景需求。",[1481,1555,1556,1561],{},[1497,1557,1558],{"align":1486},[313,1559,1560],{},"手动控制",[1497,1562,1535,1563,1566,1567,1569],{"align":1486},[26,1564,1565],{},"@Inject(CACHE_MANAGER)"," 获得 ",[26,1568,649],{}," 实例，实现更灵活的存取、删除等精细操作。",[1481,1571,1572,1577],{},[1497,1573,1574],{"align":1486},[313,1575,1576],{},"最佳实践：缓存失效",[1497,1578,1579],{"align":1486},"在数据更新时务必同步删除或更新缓存，以保障数据一致性。",[23,1581,1582],{},"希望这份介绍能帮助你系统了解并快速上手 NestJS 的缓存功能。如果希望继续了解某个部分更具体的用法，也可以告诉我～",[1584,1585,1586],"h2",{"id":1586},"参考文献",[23,1588,1589],{},"以下链接在编写时均可正常访问：",[1475,1591,1592,1602],{},[1478,1593,1594],{},[1481,1595,1596,1599],{},[1484,1597,1598],{},"资料",[1484,1600,1601],{},"说明",[1492,1603,1604,1616,1628],{},[1481,1605,1606,1613],{},[1497,1607,1608],{},[1452,1609,1612],{"href":1610,"rel":1611},"https:\u002F\u002Fdocs.nestjs.com\u002F",[1456],"NestJS 文档",[1497,1614,1615],{},"官方",[1481,1617,1618,1625],{},[1497,1619,1620],{},[1452,1621,1624],{"href":1622,"rel":1623},"https:\u002F\u002Fdocs.nestjs.com\u002Ftechniques\u002Fcaching",[1456],"Caching",[1497,1626,1627],{},"本章主题",[1481,1629,1630,1637],{},[1497,1631,1632],{},[1452,1633,1636],{"href":1634,"rel":1635},"https:\u002F\u002Fdocs.nestjs.com\u002Ffaq\u002Frequest-lifecycle",[1456],"Request lifecycle",[1497,1638,1639],{},"执行顺序",[1641,1642,1643],"style",{},"html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":56,"searchDepth":108,"depth":108,"links":1645},[1646,1647,1648,1649,1650,1651,1652,1653,1654],{"id":39,"depth":142,"text":39},{"id":330,"depth":142,"text":331},{"id":638,"depth":142,"text":639},{"id":972,"depth":142,"text":973},{"id":1127,"depth":142,"text":1128},{"id":1252,"depth":142,"text":1253},{"id":1407,"depth":142,"text":1407},{"id":1473,"depth":142,"text":1473},{"id":1586,"depth":108,"text":1586},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fcache","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fcache.md","md",{"items":1660},[1661,1665,1669,1673,1677,1681],{"path":1662,"title":1663,"description":1664,"category":10,"score":187},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fauth","认证与授权","认证（Authentication）：确认「你是谁」（如 JWT、Session）。 - 授权（Authorization）：确认「你能做什么」（如 RBAC、策略检查）。",{"path":1666,"title":1667,"description":1668,"category":10,"score":187},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice","提供者与服务","Service 是最常见的 Provider，封装业务逻辑。见 module。",{"path":1670,"title":1671,"description":1672,"category":10,"score":187},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fguards","守卫 (Guards) 与授权","守卫决定是否放行请求，常用于认证与授权。见 auth。",{"path":1674,"title":1675,"description":1676,"category":10,"score":187},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fconfig","配置管理（Config 模块）","@nestjs\u002Fconfig 加载 .env 并提供 ConfigService。见 工程化 env。",{"path":1678,"title":1679,"description":1680,"category":10,"score":187},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdatabase","数据库集成（以 TypeORM 为例）","Nest 通过 @nestjs\u002Ftypeorm 等包集成 ORM；生产环境用 migration，慎用 synchronize。亦可选用 Prisma、MikroORM 等（见 官方 Database）。",{"path":1682,"title":1683,"description":1684,"category":10,"score":187},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcron","定时任务","@nestjs\u002Fschedule 基于 cron 表达式调度任务。",{"series":1686,"title":1687,"items":1688,"index":108,"prev":1749,"next":1750},"booklet\u002Fend\u002Fnestjs\u002Fnew","new",[1689,1691,1695,1696,1698,1702,1704,1708,1710,1714,1718,1720,1724,1728,1732,1736,1739,1743,1745],{"path":1662,"title":1663,"date":1690,"pinned":15},"2025-12-23",{"path":1692,"title":1693,"date":1694,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase","NestJS 基础","2021-03-09",{"path":7,"title":8,"date":14,"pinned":15},{"path":1674,"title":1675,"date":1697,"pinned":15},"2023-08-26",{"path":1699,"title":1700,"date":1701,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcontroller","控制器与路由","2020-07-18",{"path":1682,"title":1683,"date":1703,"pinned":15},"2023-04-12",{"path":1705,"title":1706,"date":1707,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcustom-decorators","自定义装饰器","2021-09-19",{"path":1678,"title":1679,"date":1709,"pinned":15},"2023-05-26",{"path":1711,"title":1712,"date":1713,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdeploy","部署与运维","2023-01-24",{"path":1715,"title":1716,"date":1717,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Ferror","异常处理","2020-01-28",{"path":1670,"title":1671,"date":1719,"pinned":15},"2023-09-09",{"path":1721,"title":1722,"date":1723,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept","拦截器 (Interceptors)","2021-04-26",{"path":1725,"title":1726,"date":1727,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger","日志记录","2022-10-10",{"path":1729,"title":1730,"date":1731,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmiddleware","中间件 (Middleware)","2021-11-26",{"path":1733,"title":1734,"date":1735,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule","模块系统与依赖注入","2022-06-15",{"path":1737,"title":1738,"date":1701,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fpipes","管道 (Pipes) 与数据验证",{"path":1740,"title":1741,"date":1742,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fqueue","队列（Bull）","2021-07-01",{"path":1666,"title":1667,"date":1744,"pinned":15},"2024-12-02",{"path":1746,"title":1747,"date":1748,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fwebsocket","WebSocket（网关）","2022-12-14",{"path":1692,"title":1693,"date":1694,"pinned":15},{"path":1674,"title":1675,"date":1697,"pinned":15}]