需求说明

使用Flask-Caching扩展为Flask web程序页面做缓存,用以缩短同一页面的加载时间。缓存后端使用Redis服务。

当使用缓存时,用户第一次访问某一页面服务器会执行视图函数中的数据库查询、函数计算、模板渲染等工作,并将渲染后的页面数据以键值对的形式存储在Redis中,对于视图函数默认的键格式为view/<request.path>。当用户再次访问同一个页面时,服务器将会直接将Redis中保存的页面数据值返回给客户端,而不必再次执行视图函数中的代码,从而缩短页面加载时间,提升用户体验。

页面缓存适用于用户需要经常访问、包含大量数据库查询或函数计算,但是数据却不经常变动的页面。因为数据即使变动了,在不清除就缓存且缓存未到期的情况下,用户只能看到旧的页面数据。

环境配置

windows开发环境:

  • python3.7
  • Flask 2.1.1
  • Flask-Caching 1.10.1
  • Flask-DebugToolbar 0.13.1
  • redis 4.2.2(redis-py包)

Redis服务部署在Ubuntu18.04虚拟机中,版本为6.2.6。服务器IP为192.168.73.130

Flask-Caching

Flask-Caching扩展为Flask web程序提供了便捷的缓存支持,开发者只需要实例化Cache类后,为视图函数附加对应的装饰器,就也可以方便的为视图函数添加缓存支持。常用的装饰器有:

  • cached():
    常用参数有:

    • timeout:缓存的过期时间,单位为秒
    • key_prefix:缓存保存的键,默认为view/request.path,可以自行指定
    • unless:接收一个callable对象,当对象返回值为True是,不进行缓存
    • query_string:对于附带查询参数的url,将该参数设置True,可以为查询参数计算md5值并加入键中,防止在不同查询参数下都返回同一个页面
  • memoize()
    用法和cached() 基本类似,主要区别是,memoize()可以对传入被装饰方法的参数进行区分,为不同参数创建不同的缓存,相同的参数调用时直接返回缓存值。

代码示例

Flask-Caching连接Redis配置

Flask-Caching连接Redis服务,需要借助python的redis-py包,所以使用前先要安装pip install redis.
在环境变量中设置redis服务器对应的信息:

CACHE_REDIS_HOST = '192.168.73.130'
CACHE_REDIS_PORT = '6379'
CACHE_REDIS_PASSWORD = 'your password'
CACHE_REDIS_DB = '0'

为了方便,也可以直接使用redis连接的URL:

CACHE_REDIS_URL = 'redis://:<your password>@192.168.73.130:6379/0'

最后的0表示使用redis的0号数据库保存数据(redis默认有16个数据库0-15)

Flask程序代码

import os
import timefrom flask import Flask, render_template, url_for, redirect, request
from flask_caching import Cache
from flask_debugtoolbar import DebugToolbarExtensionapp = Flask(__name__)
app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = Trueapp.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev#secret_key')app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False# redis cache backend
cache = Cache(app, config={'CACHE_TYPE': 'RedisCache', 'CACHE_REDIS_URL': os.getenv('CACHE_REDIS_URL')})toolbar = DebugToolbarExtension(app)# views
@app.route('/')
def index():return render_template('index.html')@app.route('/foo')
def foo():"""不使用缓存"""time.sleep(1)return render_template('foo.html')@app.route('/bar')
@cache.cached(timeout=10 * 60)
def bar():time.sleep(1)return render_template('bar.html')@app.route('/baz')
@cache.cached(timeout=60 * 60)
def baz():time.sleep(1)return render_template('baz.html')@app.route('/qux')
@cache.cached(query_string=True)
def qux():time.sleep(1)page = request.args.get('page', 1, type=int)return render_template('qux.html', page=page)

启动程序,访问使用缓存的页面,在重载后通过DebugToolbar查看加载时间可以发现时间明显缩短。

清除缓存

  • cache.delete():传入对应的键删除cached类型缓存
  • cache.delete_memoize():传入对应键删除memoize类型缓存
  • cache.clear():清空所有缓存,一般不使用
@app.route('/update/bar')
def update_bar():"""为bar端点清除缓存"""cache.delete('view/%s' % url_for('bar'))flash('Cached data for bar have been deleted.')return redirect(url_for('index'))@app.route('/update/baz')
def update_baz():cache.delete('view/%s' % url_for('baz'))flash('Cached data for baz have been deleted.')return redirect(url_for('index'))@app.route('/update/all')
def update_all():"""清除所有缓存"""cache.clear()flash('All cached data deleted.')return redirect(url_for('index'))

问题记录

连接redis数据库时,程序报错Redis运行在保护模式。
Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the lookback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. 3) If you started the server manually just for testing, restart it with the --portected-mode no option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.

在提示信息中,已经告诉了我们如何解决这个问题,如果是单纯地进行测试,可以直接将保护模式关闭,然后重启服务即可。

如果想更安全一点,可以先使用redis-cli客户端进入服务,使用config set requirepass <password>命令为redis设置密码;然后将配置文件/etc/redis/redis.conf中的protected-mode设为yes,同时将bind选项配置为redis服务器的网卡地址(这里是192.168.73.130),然后重启服务systemctl restart redis-server

之后使用redis-cli时先使用auth <password>命令登录;使用url连接时,使用redis://:<password>@ip:port/<database>进行连接。

参考

《Python Web开发实战:入门、进阶与原理解析》 李辉

Flask-Caching使用redis缓存后端加速页面重载相关推荐

  1. MySQL建表添加乐观锁字段_Java秒杀系统优化-Redis缓存-分布式session-RabbitMQ异步下单-页面静态化...

    Java秒杀系统优化-Redis缓存-分布式session-RabbitMQ异步下单-页面静态化 项目介绍 基于SpringBoot+Mybatis搭建的秒杀系统,并且针对高并发场景进行了优化,保证线 ...

  2. .Net内部缓存System.Web.Caching.Cache 和Redis缓存缓存工厂切换

    有个问题,以前系统采用的是System.Web.Caching.Cache 但是redis缓存的流行 分布式的流行,缓存就被切换了. 但是在redis缓存的环境需要配置,有时候要切换回来. 这时候就弄 ...

  3. 布隆过滤器Redis缓存穿透雪崩击穿热点key

    目录 布隆过滤器 Redis 缓存 穿透 雪崩 击穿 热点KEY 布隆过滤器 布隆过滤器(判断某个key一定不存在) 本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构 特点是高效地插入和查询, ...

  4. Redis缓存雪崩、缓存穿透、热点Key解决方案和分析

    转载自  https://blog.csdn.net/wang0112233/article/details/79558612 https://www.sohu.com/a/230787856_231 ...

  5. 使用redis实现缓存_用下一个js实现一个简单的redis缓存

    使用redis实现缓存 For most websites, the changing pieces don't actually vary that often. That immutability ...

  6. 33:第三章:开发通行证服务:16:使用Redis缓存用户信息;(以减轻数据库的压力)

    说明: (1)声明:这个其中的区别和相同点,要清楚: ● 在[32:第三章:开发通行证服务:15:浏览器存储介质,简介:]中,前端使用[把"用户基本信息"存到Session Sto ...

  7. SpringBoot整合Redis缓存

    SpringBoot整合Redis缓存 一.缓存概念知识 1.是什么缓存 2.缓存的优缺点 3.为什么使用缓存 二.Redis概念知识 1.Redis简介 2.为什么用Redis作为缓存 3.Redi ...

  8. 面试官:谈谈Redis缓存和MySQL数据一致性问题

    前言 对于Web来说,用户量和访问量增一定程度上推动项目技术和架构的更迭和进步.可能会有以下的一些状况: 页面并发量和访问量并不多,MySQL足以支撑自己逻辑业务的发展.那么其实可以不加缓存.最多对静 ...

  9. 「中间件系列二」redis缓存

    Redis(Remote Dictionary Server) 是一个使用 C 语言编写的,开源的(BSD许可)高性能非关系型(NoSQL)的键值对数据库. Redis 可以存储键和五种不同类型的值之 ...

  10. Redis 缓存常见问题 :缓存雪崩,缓存击穿,缓存穿透,缓存预热

    文章目录 缓存雪崩 缓存击穿 缓存穿透 缓存预热 缓存雪崩 缓存雪崩指的是在短时间内,有大量缓存的键同时过期,由于缓存过期,导致此时所有的请求就直接查询数据库,而数据库很难抵挡这样巨大的压力,严重情况 ...

最新文章

  1. 你到底有几个邮箱?码云账号增加多邮箱支持!
  2. [OS复习]进程管理3
  3. 4- Mybatis 的参数深入
  4. STM32工作笔记0082---UCOSIII系统中的OSIntEnter() 与 OSIntExit()
  5. poj 2231 Moo Volume 暴力一定超时啊
  6. HDU 5510---Bazinga(指针模拟)
  7. 【rmzt】美女杨颖win7主题_8.5
  8. c语言卷积交织,卷积编码码率是什么?怎么计算
  9. Zemax 全新 22.1 版本产品现已发布
  10. 谷歌大牛 Jeff Dean 是如何成为互联网战神的
  11. 美国医院权威评估体系
  12. CVPR 2021商品识别竞赛来了!阿里达摩院主办
  13. APP抓不到包及问题解决方法
  14. 窗口的创建CreateWindow/CreateWindowEx函数使用说明
  15. “东数西算”取得新进展,发改委等四部门发文构建国家算力网络体系 | 产业区块链发展周报...
  16. 高防cdn是什么,高防cdn跟加速cdn有什么区别
  17. minio断点续传方案
  18. 关于Eclipse 3 + Lomboz 3 + Tomcat 5 设置的文档。
  19. Python育儿系列-python生成竖式运算
  20. 看图工具 -- 蓝湖 Axure 墨刀

热门文章

  1. SQL Server安装中错误该性能计数器注册表配置单元已损坏。若要继续,必须修复该性能计数器注册表配置单元的解决
  2. 基于Spring Boot的个人博客系统的设计与实现 毕业设计-附源码271611
  3. 从零开始搭建ROS小车(绪论)
  4. 短视频社交应用Socialcam关闭背后,是又一个圈钱阴谋?
  5. 推荐系统----2020会议文章集锦
  6. 自定义报表制作的注意事项——思迈特软件Smartbi报表工具
  7. 使用 Tesseract 进行文字识别
  8. [剑指Offer]-把数字翻译成字符串
  9. 图片后缀和ContentType大全
  10. 给UI/UX设计师推荐5个国外网站