flask-cache 之缓存cache实现原理

本文深入探讨了Flask-Cache对函数缓存的实现原理,包括SimpleCache的内存缓存机制,以及如何通过@cached和@memoize装饰器实现记忆参数型和无记忆参数型缓存。文章详细解释了缓存的存储结构、超期检测、key的生成和删除策略,同时展示了如何结合werkzeug的缓存功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

flask-cache的版本为:0.13.1。具体的使用例程见官方网站
flask-cache主要实现了两种功能,一种是对模板的缓存,一种是对视图函/其他函数的缓存。其中对模板缓存的原理分析请戳这里。下边我们主要写对函数的缓存原理。


源码之旅

flask-cache 对函数的缓存有两种方式,通俗的讲可以分为:
记忆参数型缓存:由@cached装饰器实现
无记忆参数型缓存:由@memoize装饰器实现

源码结构解读

flask-cache 是利用werkzeug提供的缓存函数实现的。
其中对缓存的存储是由werkzeug.contrib.cache.py文件实现的。

1)cache.py结构图

这里写图片描述
由上图可以看出,这里主要实现了SimpleCache,redis,memcached等缓存的配置功能。其中类BaseCache是其他缓存的基类,定义了缓存操作的接口操作。其方法图如下:
这里写图片描述
下边我们看一下cache.py中自己实现的一个简单的cache,SimpleCache

2)SimpleCache 实现原理

SimpleCache 是一个简单的内存缓存,只能用于单进程的环境,不能保证线程的安全性。而且也没有实现数据的持久化操作。其缓存的失效机制是由两个参数控制:threshold 与default_timeout。
基本原理是:当缓存中的key的个数超过阈值threshold ,删除生命周期大于default_timeout的key。如果default_timeout =0 表示永远不超期。

    def __init__(self, threshold=500, default_timeout=300):
        BaseCache.__init__(self, default_timeout)
        self._cache = {}
        self.clear = self._cache.clear
        self._threshold = threshold

上边是初始化方法,默认的缓存key的容量是500,默认超期时间是300s.
初始化时,首先初始化基类BaseCache,然后创建了一个字典self._cache用于存储缓存数据。

    def _prune(self):
        if len(self._cache) > self._threshold:   # 当前缓存的key的个数超过阈值
            now = time()
            toremove = []
            for idx, (key, (expires, _)) in enumerate(self._cache.items()):
                # 查找的生命周期已经超时的key
                if (expires != 0 and expires <= now) or idx % 3 == 0:
                    toremove.append(key)
            for key in toremove:
                self._cache.pop(key, None)

_prune 方法实现超期检测功能,每当进行set缓存操作时,会首先调用_prune 来校验剔除超期的元素。

    def set(self, key, value, timeout=None):
        expires = self._normalize_timeout(timeout)
        self._prune()
        self._cache[key] = (expires, pickle.dumps(value,
                                                  pickle.HIGHEST_PROTOCOL))
        return True

set函数是缓存的核心函数,其流程是首先计算期望的超期时间,然后调用_prune函数 检查校验操起元素。讲要缓存的元素放入内存的字典中,注意,这里字典的值不是直接存储数据的值,而是将数据的value进行序列化之后与expires组成元组作为key的value放入字典中。序列化的目的是为了方便对象的存储和网络传输。
get函数负责中缓存中取值,实现很简单,就是从字典中取值,然后判断是否超期,如果超期返回None

3)对函数缓存的具体实现

首先看一下flask-cache包的结构图:
这里写图片描述
init.py文件实现核心的功能:函数的缓存功能
_compat.py文件是python2与3的兼容转换
backends.py 文件是与werk

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值