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

Python2.7下如何跨多进程清除lru_cache缓存?

跨Twisted多进程清除lru_cache的实现方案

首先明确:Python标准库的lru_cache是进程本地缓存——每个Twisted启动的进程都有独立的内存空间,缓存数据完全隔离,单个进程调用cache_clear()只能清除自身的缓存,没法直接操作其他进程的缓存。要实现跨进程清除,必须通过「触发每个进程自行执行清除操作」的方式,下面是几个可行的落地方案:

方案1:基于UDP广播的IPC触发

给每个Twisted进程添加一个UDP监听,当Django端点被调用时,发送广播指令触发所有进程执行缓存清除。

步骤1:封装带注册的lru_cache装饰器

先替换标准库的lru_cache,把所有缓存函数统一注册到全局列表,方便后续批量清除:

from functools import lru_cache as std_lru_cache

# 全局存储所有带lru_cache的函数
cached_functions = []

def lru_cache(maxsize=None):
    def decorator(func):
        wrapped_func = std_lru_cache(maxsize)(func)
        cached_functions.append(wrapped_func)
        return wrapped_func
    return decorator

之后所有需要缓存的函数都用@lru_cache()代替标准的@functools.lru_cache()。

步骤2:给Twisted进程添加UDP监听

每个Twisted进程启动时加载UDP协议,监听特定端口接收清除指令:

import os
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor

class CacheClearProtocol(DatagramProtocol):
    def datagramReceived(self, datagram, address):
        # 验证指令合法性
        if datagram.strip() == b"CLEAR_LRU_CACHE":
            print(f"Clearing cache in process {os.getpid()}")
            for func in cached_functions:
                func.cache_clear()

# 启动UDP监听(本地端口9999)
reactor.listenUDP(9999, CacheClearProtocol())

步骤3:实现Django清除端点

在Django视图中发送UDP广播,通知所有进程清除缓存:

import socket
from django.http import HttpResponse

def clear_lru_cache_endpoint(request):
    # 创建UDP套接字并启用广播
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    # 发送清除指令到本地广播地址的9999端口
    sock.sendto(b"CLEAR_LRU_CACHE", ("<broadcast>", 9999))
    sock.close()
    return HttpResponse("缓存清除指令已发送至所有进程")

注意:如果进程分布在不同机器,需要调整广播地址或改用多播。

方案2:基于共享存储的定时检查

用Redis/共享文件等外部存储存一个「清除标记」,每个Twisted进程定时检查标记,触发清除操作。适合不想维护IPC通道的场景。

步骤1:Django端点设置清除标记(以Redis为例)

import redis
from django.http import HttpResponse

# 初始化Redis连接(根据项目配置调整)
redis_client = redis.Redis(host='localhost', port=6379, db=0)

def clear_lru_cache_endpoint(request):
    # 设置清除标记
    redis_client.set("lru_cache_clear_flag", "1")
    return HttpResponse("缓存清除标记已设置")

步骤2:Twisted进程添加定时检查任务

import os
from twisted.internet import task
import redis

redis_client = redis.Redis(host='localhost', port=6379, db=0)
cached_functions = []  # 同方案1的全局注册列表

def check_and_clear_cache():
    # 检查标记是否存在
    if redis_client.get("lru_cache_clear_flag") == b"1":
        print(f"Clearing cache in process {os.getpid()}")
        for func in cached_functions:
            func.cache_clear()
        # 清除标记,避免重复执行
        redis_client.set("lru_cache_clear_flag", "0")

# 每1秒检查一次(可根据需求调整间隔)
cache_check_loop = task.LoopingCall(check_and_clear_cache)
cache_check_loop.start(1)

缺点:缓存清除有延迟,适合对实时性要求不高的场景。

方案3:基于系统信号的触发

给每个Twisted进程注册自定义信号处理,Django端点找到所有Twisted进程PID并发送信号,触发缓存清除。

步骤1:Twisted进程注册信号处理

import os
import signal

cached_functions = []  # 同方案1的全局注册列表

def handle_cache_clear(signum, frame):
    print(f"Received clear signal in process {os.getpid()}")
    for func in cached_functions:
        func.cache_clear()

# 注册SIGUSR1信号(可选用其他未被占用的信号)
signal.signal(signal.SIGUSR1, handle_cache_clear)

步骤2:Django端点发送信号到所有Twisted进程

需要安装psutil库(Python2.7需安装psutil<5.0版本,因为高版本不再支持Python2.7):

import psutil
import signal
from django.http import HttpResponse

def clear_lru_cache_endpoint(request):
    # 遍历所有进程,识别Twisted进程
    for proc in psutil.process_iter(['name', 'cmdline']):
        try:
            # 根据进程名或命令行判断(需替换为你的Twisted进程标识)
            if 'twisted' in proc.name() or 'your_twisted_entry.py' in proc.cmdline():
                proc.send_signal(signal.SIGUSR1)
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            continue
    return HttpResponse("缓存清除信号已发送至所有Twisted进程")

优点:实时性好,缺点需要进程识别准确,且需足够权限发送信号。

关键注意事项

  • 必须用自定义的lru_cache装饰器替换所有标准库的调用,否则无法批量收集缓存函数。
  • 所有方案的核心逻辑都是「让每个进程自行执行cache_clear()」,因为跨进程无法直接操作对方内存中的缓存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 15:10:29