數據存在哪?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