1.介绍

缓存介绍

如果您的应用运行很慢,那就尝试引入一些缓存吧。好吧,至少这是提高表现最简单的方法。缓存的工作是什么呢?比如说您有一个需要一段时间才能完成的函数,但是这个函数的返回结果可能在5分钟之内都是足够有效的,因此您可以将这个结果放到缓存中一段时间,而不用反复计算
如果同一个请求会被多次调用,每次调用都会消耗很多资源,并且每次返回的内容都相同,就该使用缓存了

Flask 本身并不提供缓存功能,但是作为Flask 基础的 Werkzeug 库,则提供了一些基础的缓存支持。

Werkzeug 支持多种缓存后端,通常的选择是 Memcached 服务器。

缓存类型

我们来了解一下flask-caching支持的缓存类型:

flask-caching内置的缓存类型CACHE_TYPE有:NullCache、SimpleCache、FileSystemCache、RedisCache、RedisSentinelCache、RedisClusterCache、UWSGICache、MemcachedCache、SASLMemcachedCache和SpreadSASLMemcachedCache(在Flask-Caching2.0中删除)。

其中:

NullCache:无缓存,其配置参数可以有:

  • CACHE_NO_NULL_WARNING:不会抛出警告信息;
  • CACHE_DEFAULT_TIMEOUT:如果未指定超时,则使用默认超时,时间单位是秒。

SimpleCache:使用本地python字典进行存储,非线程安全,其配置参数可以有:

  • CACHE_DEFAULT_TIMEOUT:如果未指定超时,则使用默认超时,时间单位是秒;
  • CACHE_THRESHOLD:最大缓存数;
  • CACHE_IGNORE_ERRORS:其值为True时,在删除过程中发生的任何错误将被忽略;其值为False时,在删除过程中第一个错误时停止删除;

FileSystemCache:使用文件系统来存储缓存的值,其配置参数可以有:

  • CACHE_DEFAULT_TIMEOUT:如果未指定超时,则使用默认超时,时间单位是秒;
  • CACHE_IGNORE_ERRORS:其值为True时,在删除过程中发生的任何错误将被忽略;其值为False时,在删除过程中第一个错误时停止删除;
  • CACHE_DIR:存储缓存的目录;
  • CACHE_THRESHOLD:最大缓存数;
  • CACHE_OPTIONS:在缓存类实例化期间传递的可选字典。

RedisCache:使用Redis作为缓存后端,其配置参数可以有:

  • CACHE_DEFAULT_TIMEOUT:如果未指定超时,则使用默认超时,时间单位是秒;
  • CACHE_KEY_PREFIX:所有它都可以用于应用程序的应用程序使用相同的键;
  • CACHE_OPTIONS:在缓存类实例化期间传递的可选字典;
  • CACHE_REDIS_HOST:Redis 服务器主机;
  • CACHE_REDIS_PORT:Redis 服务器端口,默认为 6379;
  • CACHE_REDIS_PASSWORD:服务器的 Redis 密码;
  • CACHE_REDIS_DB :Redis db(从零开始的数字索引),默认为 0;
  • CACHE_REDIS_URL:| 连接到 Redis 服务器的 URL,例子redis://user:password@localhost:6379/2 。

RedisSentinelCache:使用Redis哨兵模型缓存,其配置参数可以有:

  • CACHE_KEY_PREFIX:所有它都可以用于应用程序的应用程序使用相同的键;
  • CACHE_REDIS_SENTINELS:Redis哨兵地址的列表或元组;
  • CACHE_REDIS_SENTINEL_MASTER:哨兵配置中的主服务器的名称
  • CACHE_REDIS_PASSWORD:服务器的 Redis 密码;
  • CACHE_REDIS_DB:Redis db(从零开始的数字索引),默认为 0。

RedisClusterCache:使用Redis自动分区缓存,其配置参数可以有:

  • CACHE_KEY_PREFIX:所有它都可以用于应用程序的应用程序使用相同的键;
  • CACHE_REDIS_CLUSTER:一串以逗号分隔的 Redis 集群节点地址;
  • CACHE_REDIS_PASSWORD:服务器的 Redis 密码。

MemcachedCache:使用memcached服务器作为缓存后端,支持pylibmc或memcache或Google应用程序引擎memcache库,其配置参数可以有:

  • CACHE_DEFAULT_TIMEOUT:如果未指定超时,则使用默认超时,时间单位是秒;
  • CACHE_KEY_PREFIX:所有它都可以用于应用程序的应用程序使用相同的键;
  • CACHE_MEMCACHED_SERVERS:服务器地址的列表或元组。

注意:Flask-Caching不会将额外的配置选项传递给memcached后端,要向这些缓存添加其他配置。

SASLMemcachedCache:启用SASL的memcached服务器作为缓存后端,其配置参数可以有:

  • CACHE_DEFAULT_TIMEOUT:如果未指定超时,则使用默认超时,时间单位是秒;
  • CACHE_KEY_PREFIX:所有它都可以用于应用程序的应用程序使用相同的键;
  • CACHE_OPTIONS:在缓存类实例化期间传递的可选字典;
  • CACHE_MEMCACHED_SERVERS:服务器地址的列表或元组;
  • CACHE_MEMCACHED_USERNAME:使用memcached进行SASL身份验证的用户名;
  • CACHE_MEMCACHED_PASSWORD:使用memcached进行SASL身份验证的密码。

UWSGICache:使用uwsgi服务器作为缓存,其配置参数可以有:

  • CACHE_UWSGI_NAME:要连接的uwsgi缓存实例的名称,例如:mycache @ localhost :3031,默认为空字符串;

注意:该UWSGICache没有维护也没有测试,不建议使用。

 

2.安装模块

pip3 install redis -i https://pypi.douban.com/simple
pip3 install flask-caching -i https://pypi.douban.com/simple

3.创建一个Flask-Cache的实例

3.1介绍

有很多种实例方式,这里介绍我最常用的一种

3.2 第一种使用 

view(推荐)

from flask import Flask
from flask_cache import Cache

config={
              'CACHE_TYPE': 'redis',          # Use Redis
              'CACHE_REDIS_HOST': 'abc.com',  # Host, default 'localhost'
              'CACHE_REDIS_PORT': 6379,       # Port, default 6379
              'CACHE_REDIS_PASSWORD': '111',  # Password
              'CACHE_REDIS_DB': 2
}         


app = Flask(__name__)
# 实例
cache = Cache(config=config)
# 绑定到app上
cache.init_app(app)

3.3 其他种使用

from flask import Flask
from flask_caching import Cache
#配置RedisCache缓存类型参数值,我们使用本地的redis,没有密码
config={     
    'CACHE_TYPE':'redis',  #使用redis作为缓存
    'CACHE_REDIS_HOST':'127.0.0.1',  #redis地址
    'CACHE_REDIS_PORT':6379  #redis端口号
}

app = Flask(__name__)
#初始化缓存
cache=Cache(app=app,config=config)  #创建Cache对象
#或使用init_app()初始化缓存
#cache=Cache()         #创建Cache对象
#cache.init_app(app=app,config=config)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

3.3 介绍参数

CACHE_TYPE:设置缓存的类型

# 下面五个参数是所有的类型共有的
CACHE_NO_NULL_WARNING = "warning" # null类型时的警告消息
CACHE_ARGS = []	# 在缓存类实例化过程中解包和传递的可选列表,用来配置相关后端的额外的参数
CACHE_OPTIONS = {}	# 可选字典,在缓存类实例化期间传递,也是用来配置相关后端的额外的键值对参数
CACHE_DEFAULT_TIMEOUT # 默认过期/超时时间,单位为秒
CACHE_THRESHOLD	# 缓存的最大条目数

CACHE_TYPE = null # 默认的缓存类型,无缓存
CACHE_TYPE = 'simple' # 使用本地python字典进行存储,线程非安全

CACHE_TYPE = 'filesystem' # 使用文件系统来存储缓存的值
CACHE_DIR = "" # 文件目录

CACHE_TYPE = 'memcached' # 使用memcached服务器缓存
CACHE_KEY_PREFIX # 设置cache_key的前缀
CAHCE_MEMCACHED_SERVERS	# 服务器地址的列表或元组
CACHE_MEMCACHED_USERNAME # 用户名
CACHE_MEMCACHED_PASSWORD # 密码

CACHE_TYPE = 'uwsgi' # 使用uwsgi服务器作为缓存
CACHE_UWSGI_NAME # 要连接的uwsgi缓存实例的名称

CACHE_TYPE = 'redis' # 使用redis作为缓存
CACHE_KEY_PREFIX # 设置cache_key的前缀
CACHE_REDIS_HOST  # redis地址
CACHE_REDIS_PORT  # redis端口
CACHE_REDIS_PASSWORD # redis密码
CACHE_REDIS_DB # 使用哪个数据库
# 也可以一键配置
CACHE_REDIS_URL	连接到Redis服务器的URL。示例redis://user:password@localhost:6379/2

3.5 配置多个缓存实例

cache1 = Cache()
cache2 = Cache()
cache1.init_app(app, config={ 'CACHE_TYPE' : 'redis','CACHE_REDIS_HOST':'192.168.1.20',
                             'CACHE_REDIS_PORT':'6390'})
cache2.init_app(app, config={ 'CACHE_TYPE' : 'redis','CACHE_REDIS_HOST':'192.168.1.21',
                             'CACHE_REDIS_PORT':'6390'})

4.使用

装饰器,装饰无参数函数,缓存该函数

使用格式

@cache.cached(timeout=None,key_prefix=None,unless=None,forced_update=None,query_string=False)

参数介绍 

  • timeout为超时时间,默认为None,即永不过期
  • key_prefix:缓存指定的函数;缓存项键值的前缀,默认为”view/%s”
  • unless:是否启用缓存,如果为True,不启用缓存;默认为None,即缓存有效
  • forced_update:缓存是否实时更新,如果为True,无论是否过期都将更新缓存;
  • query_string:为True时,缓存键是先将参数排序然后哈希的结果。

实例 

@app.route('/test2')
@cache.cached(timeout=30) # 专门为装饰视图函数准备的装饰器
def test2():
    print('111')
    return 'ok'

装饰器,装饰有参数函数,缓存该函数

使用格式

@cache.memoize(timeout=None,make_name=None,unless=None,forced_update=None,query_string=False)

参数介绍 

与cache.cached()方法类似,区别为cache.memoize有make_name,其作用是设置函数的标志,如果没有就使用装饰的函数。

Flask-Cache还提供了另一个装饰器方法”cache.memoize()”,它与”cache.cached()”的区别就是它会将函数的参数也放在缓存项的键值中:

我们再次访问”/list”地址,对于不同的参数,”method called”会一直在控制台上打印出,而对于相同的参数,第二次就不会打印了。

所以对于带参数的函数,你要使用”cache.memoize()”装饰器,而对于不带参数的函数,它同”cache.cached()”基本上一样。

”cache.memoize()”装饰器也有三个参数,

”timeout”和”unless”参数同”cache.cached()”一样,

就是第二个参数”make_name”比较特别,它是一个回调函数,传入的是被装饰的函数名,返回是一个字符

实例 

@cache.memoize(timeout=50)
def create_list(num):
    print 'method create_list called'
    l = []
    for i in range(num):
        l.append(str(i))
    return l

@app.route('/list/<int:num>')
def list(num):
    return ', '.join(create_list(num))

 cache.cached用来装饰普通函数

参数:

        key_prefix:设置函数的标志,如果没有就使用装饰的函数 # 其他参数同cached

我们访问”/list”地址时,第一次控制台上会有”method called”输出,第二次就不会了,说明缓存起效了。

装饰普通函数时必须指定明确的”key_prefix”参数,因为它不像视图函数,可以使用请求路径”request.path”作为缓存项的键值。

如果函数带参数,对于不同的参数调用,都会使用同一缓存项,即返回结果一样。

@cache.cached(timeout=50, key_prefix='get_list')
def get_list():
    print 'method get_list called'
    return ['a','b','c','d','e']

@app.route('/list')
def list():
    return ', '. join(get_list())

@cache.memoize用来装饰普通函数

参数

参数:

        make_name:设置函数的标志,如果没有就使用装饰的函数 # 其他参数同cached

我们访问”/list”地址时,第一次控制台上会有”method called”输出,第二次就不会了,说明缓存起效了。

装饰普通函数时必须指定明确的”make_name”参数,因为它不像视图函数,可以使用请求路径”request.path”作为缓存项的键值。

如果函数带参数,对于不同的参数调用,都会使用同一缓存项,即返回结果一样。

实例

# 装饰有参的函数
@cache.memoize(timeout=60, make_name='get_result')
def get_result(n):
    return str(n)

@cache.cached(timeout=30)
def test_xxx():
    return 'this is a test'

缓存键值对

实例一

# __init__.py
from flask import Flask, current_app, make_response, request
from test import get_result, test_xxx
from exsentions import cache

app = Flask(__name__)
app.config['SECRET_KEY'] = '123'
cache.init_app(app, config={ 'CACHE_TYPE' : 'redis','CACHE_REDIS_HOST':'192.168.1.20',
                             'CACHE_REDIS_PORT':'6390'})

@app.route('/test1')
def test():
    cache.set('name','xiaoming', timeout=30)
    cache.set('person',{'name':'aaa', 'age':20})
    x = cache.get('name')
    print(x)
    cache.set_many([('name1','hhh'),('name2','jjj')])
    print(cache.get_many("name1","name2"))
    print(cache.delete("name"))
    print(cache.delete_many("name1","name2"))
    return res

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=80, debug=True)

实例二 

#设置
cache.set(key,value,timeout=None) #设置一个缓存对象
cache.set_many([(key,value),(key,value),...,(key,value)],timeout=None) #设置多个缓存对象
#获取
cache.get(key)        #获取一个缓存对象
cache.get_many(key1,key2,....)  #获取多个缓存对象
#删除
cache.get.delete(key)      #删除一个缓存对象
cache_delete_many(key1,key2,...) #删除多个缓存对象
cache.clear()     #删除所有缓存对象

删除缓存

对于普通缓存,你可以使用”delete()”方法来删除缓存项,而对于”memoize”缓存,你需要使用”delete_memoized”方法。如果想清除所有缓存,可以使用”clear()”方法。

cache.delete('get_list')                     # 删除'get_list'缓存项
cache.delete_many('get_list', 'view_hello')  # 同时删除'get_list'和'view_hello'缓存项
cache.delete_memoized('create_list', 5)      # 删除调用'create_list'函数并且参数为5的缓存项
cache.clear()                                # 清理所有缓存

Jinja2模板中使用缓存

其实在Jinja2模板中,我们还可以使用”{% cache %}”语句来缓存模板代码块:

这样”{% cache %}”和”{% endcache %}”语句中所包括的内容就会被缓存起来。”{% cache %}”语句的第一个参数是”timeout”过期时间,默认为永不过期;第二个参数指定了缓存项的键值,如果不设,键值就是”模板文件路径”+”缓存块的第一行”。

{% cache 50, 'temp' %}
<p>This is under cache</p>
{% endcache %}

然后在代码中,我们可以这样获取缓存项实际的键值:

打印出来看看,你会发现实际的键值其实是”_template_fragment_cache_temp”。如果你要删除该缓存项,记得要传入实际的键值,而不是模板上定义的’temp’。

from flask_cache import make_template_fragment_key
key = make_template_fragment_key('temp')

本文参考

(253条消息) Flask-Cache——缓存_qq_41134008的博客-CSDN博客https://blog.csdn.net/qq_41134008/article/details/105698861flask插件系列之flask_caching缓存 - 倥偬时光 - 博客园 (cnblogs.com)https://www.cnblogs.com/cwp-bg/p/9687005.html(253条消息) flask缓存机制_冰_戒的博客-CSDN博客_flask缓存机制https://blog.csdn.net/huang_yong_peng/article/details/82622077

Flask框架——flask-caching缓存 - 知乎 (zhihu.com)icon-default.png?t=M85Bhttps://zhuanlan.zhihu.com/p/544198743 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐