数据存在哪?html
多级缓存html5
保存哪些数据 ? 数据以什么形式(类型)保存?python
一个数值mysql
数据库记录redis
比较通用,缓存一个数据能够被多个视图利用,节省空间算法
方式:sql
Caching at the object level 缓存数据对象级别数据库
mysql 中有用户的我的信息表 每条记录 是一个用户的数据 一个数据实体 user:1 -> user_id ,name mobile profile_photo intro certi user:20 -> user_id ,name mobile profile_photo intro certi
Caching at the database query level 缓存数据库查询级别django
sql = 'select * from ..inner join where ... group by order by limit' -> query_results hash(sql) -> 'wicwiugfiwuegfwiugiw238' md5(sql) 缓存 数据名称 数据内容 'wicwiugfiwuegfwiugiw238' -> query_results 使用的时候 sql -> md5(sql) -> 'wicwiugfiwuegfwiugiw238'
一个视图的响应结果json
@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 # /articles?ch=123 视图的结果resuls 缓存 # 下一次再访问 ‘/articles?ch=123’
只针对 h5页面 (html5) 网页
方式
若是是服务器端渲染 (先后端不分离)
@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
页面静态化 算是一种页面缓存方式
针对的是外部缓存 redis
字符串形式
user:1 -> user_id ,name mobile profile_photo intro certi user1 -> User()对象 -> user1_dict key value user:1 -> json.dumps(user1_dict) pickle.dumps() json: 1. 只能接受 列表 字典 bytes类型 2. json转换成字符串 效率速度慢 pickle : 1. 基本支持python中的全部类型,(包括自定义的类的对象) 2. json转换成字符串 效率速度 快
非字符串形式
user:1 -> user_id ,name mobile profile_photo intro certi user1 -> User()对象 -> user1_dict key value user:1 -> hash { name: xxx, moible: xxx photo: xxx }
缓存数据必定要设置有效期,缘由/做用:
通用的有效期策略:
定时过时
set a 100 有效期 10min set b 100 有效期 20min
开启一个计时器计时,当有效期到达以后 清理数据, 能够理解为每一个数据都要单独维护一个计时器
缺点: 耗费性能
惰性过时
保存数据 设置有效期后 不主动维护这个数据的有效期,不计时,只有在再次访问这个数据(读写)的时候,判断数据是否到期,若是到期清理并返回空,若是没到期,返回数据
按期过时
Redis的有效期策略 : 惰性过时 + 按期过时
思考:
若是在redis中保存了一条数据,设置有效期为10min,可是数据设置以后 再无操做, 请问 10min以后 这条数据是否还在redis的内存中? 答案: 还可能存在
背景: redis的数据有效期策略不能保证数据真正的即时被清理,可能形成空间浪费,再有新的数据的时候,没地方能够存存储, 为了存储新数据,须要清理redis中的一批数据,腾出空间保存新数据
淘汰策略 指 删除哪些数据
LRU(Least recently used,最近最少使用)
思想: 认为 越是最近用过的数据,接下来使用的机会越大,应该清理那些好久之前使用过的数据
cache_data = [ cache1 时间最近 cache2 cache5 cache4 cache3 时间最远 ] 操做过cache3 cache_data = [ cache3 cache1 时间最近 cache2 cache5 cache4 ] 增长cache6 cache_data = [ cache6 cache3 cache1 时间最近 cache2 cache5 ]
LFU (Least Frequently Used, 最少使用) 以频率 次数来考虑
思想: 认为使用次数越多的数据,接下来使用的机会越大,应该清理那些使用次数少的数据
cache_data = { cache1 : 100 cache2: 2 cache5: 23 cache4: 89 cache3 : 10000 } 操做了cache2 cache_data = { cache1 : 100 cache2: 3 cache5: 23 cache4: 89 cache3 : 10000 } 新增 cache6 cache_data = { cache1 : 100 cache5: 23 cache4: 89 cache3 : 10000 cache6: 1 } cache_data = { cache1 : 100 -> 50 cache5: 23 -> 11 cache4: 89 -> 45 cache3 : 10000 -> 5000 cache6: 1 -> 1 }
redis 4.x 版本以后 增长了两种
redis中的配置
maxmemory <bytes> 指明redis使用的最大内存上限 maxmemory-policy volatile-lru 指明内存淘汰策略
应用程序如何使用缓存
修改了mysq中的数据,如何处理redis缓存中的数据
先更新数据库,再更新缓存
先更新数据库,再删除缓存 发生问题的概率最小 ,负面影响最小
redis数据类型的设计 (redis数据类型选型)
redis 的list set hash zset 数据是不容许嵌套的, 数据元素都是字符串
用户我的信息数据 (相似参考的 文章缓存 评论缓存)
user1 -> User1 -> name mobile photo user2 -> User2 ->
key value users:info -> str X json.dumps({'user1': cache_data, 'user2': cache_data}) list set X [json.dumps(user1_dict), json.dumps(user2_dict)] hash { 'user1': json.dumps(user1_dict), 'user2': json.dumps(user2_dict) } zset X member 成员 score 分数/权重 json.dumps(user1_dict) user_id
考虑有效期:
redis中的有效期不能对一条记录中的不一样字段单独设置,最小只能给一条记录设置有效期
全部人只能有一个有效期,很差 缓存雪崩
不采用
方式2 每一个用户在redis中单独一条记录
user1 -> User1 -> name mobile photo user2 -> User2 -> key value user:{user_id}:info user:1:info user:2:info -> str json.dumps(user2_dict) hash { "name": xxx, "mobile": xx 'photo':xxx } str: 占用空间小 头条项目 为了保存更多的缓存数据 选择字符串 hash: 存取灵活
用户关注列表信息数据 ( 相似的还有 用户的文章列表 文章的评论列表 用户的粉丝列表等)
须要缓存的是关注里中 关注的用户的user_id
1号用户关注过 2 3 4 5 6 7
每一个人单独一条redis记录
key value user:{user_id}:follows user:1:follows user:2:follows -> str json.dumps([2,3,4,5..user_id]) list set X ['2','3','4', 'use_id',..] hash X field value user_id_2 follow_time user_id_3 follow_time zset 有序集合 既能去重 还有序 member score user_id_2 follow_time user_id_3 follow_time 时间戳 str 用户若是关注的人过多,整取数据不方便,并且列表通常是要分页取 zset 能够批量分页取数据 还能排序 头条项目选择zset 更新数据库后 添加数据
保存的数据
阅读历史 (文章id列表)
方式一: 全部人一条记录 X
key value users:read:history str json.dumps({'user_1': [], user_2:[]}) list set X hash { "user_1": '2,3,4,5', "user_2": '100, 20, 30' } zset member score article_id user_id ‘2,3,4,5' user_id1 '100, 20, 30' user_id2
方式二: 每人一条记录
key value user:{user_id}:read:history user:1:read:history user:2:read:history -> list [artilce_id, 2, 3, 4, ...] set 没有顺序 X (artilce_id, 2, 3, 4, ...) hash X article_id read_time 2 16724383275342 3 163232763827822 zset 选择 member score article_id read_time 2 16724383275342 3 163232763827822
统计数据
方式一
key value user:{user_id}:statistic user:1:statistic user:2:statistic -> hash { 'article_count': 120, "follow_count": xx, "fans_count": xxx, .. }
方式二: 采用
考虑运营平台可能须要对产品进行全平台大排名,好比 筛选发布文章数量最多的前20名用户 top问题
每一个统计指标 一条redis记录(保存全部用户这个统计指标的数据)
key value statistic:user:follows statistic:user:fans statistic:user:articles -> zset mebmer score user_id article_count 1 100 2 3 3 11