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

Flask应用中如何用cachetools实现缓存过期返回旧值并后台更新

实现带过期返回+后台更新的TTL缓存方案

针对你在Flask应用中遇到的远程API请求超时问题,我们可以基于cachetools扩展实现缓存过期时返回旧值、后台异步更新的逻辑,核心思路是用线程在后台执行耗时任务,同时让请求快速响应。

核心实现步骤

1. 初始化缓存与线程控制工具

我们需要TTLCache存储缓存数据,用线程锁和更新标记避免重复触发后台任务:

from cachetools import TTLCache
import threading
from flask import Flask

app = Flask(__name__)

# 初始化TTL缓存:最多存1条数据,TTL设为3600秒(可根据需求调整)
cache = TTLCache(maxsize=1, ttl=3600)
# 线程锁,保证更新操作的线程安全
update_lock = threading.Lock()
# 标记是否正在后台更新缓存
is_updating = False

2. 封装耗时的远程API调用函数

假设这是你的耗时任务(替换为实际远程API请求逻辑):

def fetch_remote_data():
    # 模拟耗时操作:实际场景替换为远程API请求代码
    import time
    time.sleep(60)  # 模拟1分钟的耗时请求
    return {"data": "远程API返回的最新数据", "timestamp": time.time()}

3. 实现带后台更新的缓存逻辑

封装函数处理缓存读取、过期判断和后台更新逻辑:

def get_cached_data():
    global is_updating
    # 先尝试获取缓存值
    cached_value = cache.get('remote_data')
    
    # 检查缓存是否过期或不存在
    cache_expired_or_empty = (cached_value is None) or (cache.ttl() <= 0)
    
    # 如果需要更新且当前没有在更新,启动后台线程
    if cache_expired_or_empty and not is_updating:
        with update_lock:
            # 双重检查,防止多线程并发触发重复更新
            if not is_updating:
                is_updating = True
                # 启动后台线程执行更新,daemon=True保证Flask退出时线程自动终止
                threading.Thread(target=update_cache, daemon=True).start()
    
    # 无论缓存是否过期,优先返回现有缓存(首次预加载前可能返回None,需处理)
    return cached_value

def update_cache():
    global is_updating
    try:
        # 执行耗时的远程API请求
        new_data = fetch_remote_data()
        # 更新缓存
        cache['remote_data'] = new_data
    finally:
        # 无论任务成功失败,都标记更新结束,保证后续请求能正常触发新的更新
        with update_lock:
            is_updating = False

4. Flask路由集成

在路由中调用缓存函数,快速返回响应:

@app.route('/')
def index():
    data = get_cached_data()
    # 首次启动预加载前,data可能为None,这里返回提示或默认值
    if not data:
        return "数据加载中,请稍后刷新", 202
    return f"当前数据:{data['data']} | 生成时间:{data['timestamp']}"

5. 启动时预加载缓存

为避免首次请求等待,在Flask启动时提前加载一次缓存:

if __name__ == '__main__':
    # 启动前预加载缓存,后续请求直接使用缓存值
    cache['remote_data'] = fetch_remote_data()
    app.run(debug=True)

关键细节说明

  • 线程安全:通过update_lock和双重检查机制,避免多请求并发触发重复的耗时任务,减少资源浪费。
  • 异常容错:update_cache中的try/finally块保证即使远程API请求失败,更新标记也会被重置,后续请求仍能触发新的更新尝试。
  • 响应速度:无论缓存是否过期,请求都会立即返回现有缓存值,彻底解决页面超时问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:35:25