🏆🏆🏆教程全知识点简介:1.APScheduler任务调度涵盖安装配置、使用方式、调度器Scheduler、执行器executors、触发器Trigger等核心组件。2. RPC远程过程调用包括RPC概念、背景用途、优缺点分析。3. Protocol Buffers数据序列化涉及文档结构、注释语法、数据类型、枚举类型、消息类型(字段编号、字段规则、嵌套类型、保留字段、默认值)。4. 客户端开发包含头条首页新闻推荐接口编写。5. 即时通讯技术涵盖需求场景、传统推送实现、Socket.IO(Python服务器端开发、事件处理)。6. Elasticsearch搜索引擎包括简介原理、倒排索引、分析器、相关性排序、集群概念、IK中文分析器、索引类型、文档操作(索引文档、获取文档、判断存在、更新删除)、Logstash数据导入、查询(基本查询、高级查询)、全文检索实现、Python客户端使用、联想提示(拼写纠错、自动补全)。7. 单元测试涵盖测试分类、基本写法、测试必要性。8. 服务器部署包括Gunicorn、Supervisor配置管理。9. 项目开发流程涉及产品介绍、原型图UI图、技术架构、开发环境(ToutiaoWeb虚拟机、Pycharm远程开发)。10. 数据库技术包含ORM理解、SQLAlchemy映射构建、数据库连接设置、模型类字段选项。11. 分布式系统涵盖分布式ID方案选择、Twitter Snowflake算法(64位ID划分、最大取值计算、移位偏移计算、序号循环掩码、时间戳处理)。12. Redis数据库包括Redis持久化机制。13. Git工作流涵盖Gitflow工作流(工作方式、历史分支、功能分支、发布分支、维护分支)、调试方法。14. 身份认证技术包含JWT、JWS、JWE概念、Python库使用、项目封装实施方案。15. 对象存储涉及OSS对象存储、七牛云存储服务。16. 缓存系统包括缓存架构、缓存数据保存方式、缓存有效期TTL、缓存淘汰策略、缓存问题(缓存穿透、缓存雪崩)、头条项目缓存设计(User Cache、Article Cache、Announcement Cache)、持久存储设计(阅读历史、搜索历史、统计数据)。
📚📚仓库code.zip 👉直接-->: gitlab.com/yinuo_112/B… 🍅🍅
✨ 本教程项目亮点
🧠 知识体系完整:覆盖从基础原理、核心方法到高阶应用的全流程内容
💻 全技术链覆盖:完整前后端技术栈,涵盖开发必备技能
🚀 从零到实战:适合 0 基础入门到提升,循序渐进掌握核心能力
📚 丰富文档与代码示例:涵盖多种场景,可运行、可复用
🛠 工作与学习双参考:不仅适合系统化学习,更可作为日常开发中的查阅手册
🧩 模块化知识结构:按知识点分章节,便于快速定位和复习
📈 长期可用的技术积累:不止一次学习,而是能伴随工作与项目长期参考
🎯🎯🎯全教程总章节

🚀🚀🚀本篇主要内容
缓存
缓存架构
脑中的直观反应

计算机体系结构中的缓存

多级缓存

头条项目的方案
-
SQLAlchemy起到一定的本地缓存作用
- 在同一请求中多次相同的查询只查询数据库一次,SQLAlchemy做了本地缓存(类似Django中的Queryset查询结果集)
-
使用Redis构建一层缓存
缓存数据
缓存数据的类型
在设计缓存的数据时,可以缓存以下类型的数据
- 一个数值
例如
- 用户状态
如:user:{user_id}: enable
-
数据库记录,
- Caching at the object level
以数据库对象的角度考虑, 应用更普遍
例如, 用户的基本信息
user = User.query.filter_by(id=1).first()
user -> User对象
{
'user_id':1,
'user_name': 'python',
'age': 28,
'introduction': ''
}
- Caching at the database query level
以数据库查询的角度考虑,应用场景较特殊,一般仅针对较复杂的查询进行使用
query_result = User.query.join(User.profile).filter_by(id=1).first()
-> sql = "select a.user_id, a.user_name, b.gender, b.birthday from tbl_user as a inner join tbl_profile as b on a.user_id=b.user_id where a.user_id=1;"
# hash算法 md5
query = md5(sql) # 'fwoifhwoiehfiowy23982f92h929y3209hf209fh2'
# redis
setex(query, expiry, json.dumps(query_result))
- 一个视图的响应结果
@route('/articles')
@cache(exipry=30*60)
def get_articles():
ch = request.args.get('ch')
articles = Article.query.all()
for article in articles:
user = User.query.filter_by(id=article.user_id).first()
comment = Comment.query.filter_by(article_id=article.id).all()
results = {...} # 格式化输出
return results
# redis
# '/artciels?ch=1': json.dumps(results)
- 一个页面
@route('/articles')
@cache(exipry=30*60)
def get_articles():
ch = request.args.get('ch')
articles = Article.query.all()
for article in articles:
user = User.query.filter_by(id=article.user_id).first()
comment = Comment.query.all()
results = {...}
return render_template('article_temp', results)
# redis
# '/artciels?ch=1': html
缓存数据的保存方式
- 序列化字符串
如
# 序列化 json字符
# setex('user:{user_id}:info')
setex('user:1:info', expiry, json.dumps(user_dict))
-
优点
- 存储字符串节省空间
-
缺点
- 序列化有时间开销
- 更新不方便(一般直接删除)
-
Redis的其他数据类型,如hash、set、zset
如
hmset('user:1:info', user_dict)
- 优点
* 读写时不需要序列化转换
* 可以更新内部数据
-
缺点
-
相比字符串,采用复合结构存储空间占用大
-
缓存有效期与淘汰策略
有效期 TTL (Time to live)
设置有效期的作用:
-
节省空间
-
做到数据弱一致性,有效期失效后,可以保证数据的一致性
Redis的过期策略
过期策略通常有以下三种:
- 定时过期
每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
setex('a', 300, 'aval')
setex('b', 600, 'bval')
- 惰性过期
只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
- 定期过期
每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。
Redis中同时使用了惰性过期和定期过期两种过期策略。
Redis过期删除采用的是定期删除,默认是每100ms检测一次,遇到过期的key则进行删除,这里的检测并不