Redis第2??4??課 緩存的使用梧乘、設(shè)計(jì)袄膏、優(yōu)化

一默色、緩存的受益與成本

1. 受益

(1)加速讀寫(xiě)

  • 通過(guò)緩存加速讀寫(xiě)速度:CPU L1/L2/L3 Cache谎势、Linux Page Cache加速硬盤(pán)讀寫(xiě)、瀏覽器緩存虐沥、Ehcache緩存等

(2)降低后端負(fù)載(MySQL)

2.成本

(1)數(shù)據(jù)不一致:緩存層和數(shù)據(jù)層有時(shí)間窗口不一致熊经,和更新策略有光
(2)代碼維護(hù)成本:多了一層緩存邏輯
(3)運(yùn)維成本:例如Redis Cluster

3.場(chǎng)景

  1. 降低后端負(fù)載
    對(duì)高消耗的SQL: join結(jié)果集 / 分組統(tǒng)計(jì)結(jié)果緩存
  2. 加速請(qǐng)求相應(yīng)
    利用Redis / Memcache 優(yōu)化IO響應(yīng)時(shí)間
  3. 大量寫(xiě)合并為批量寫(xiě)
    如計(jì)數(shù)器先Redis累加再批量寫(xiě)DB


二、緩存更新策略

  1. LRU / LFU / FIFO 算法剔除:例如maxmemory-policy
    先刪掉
  2. 超時(shí)剔除:例如:expire
  3. 主動(dòng)更新:開(kāi)發(fā)控制key的生命周期
\color{green}{策略} \color{green}{一致性} \color{green}{維護(hù)成本}
LUR/LIRS算法剔除 最差
超時(shí)剔除 較差
主動(dòng)更新
兩條建議
  1. 低一致性:最大內(nèi)存和淘汰策略
  2. 高一致性:超時(shí)剔除和主動(dòng)更新結(jié)合欲险,最大內(nèi)存和淘汰策略兜底
    無(wú)法保證將來(lái)某一天內(nèi)存增上去了奈搜,而你監(jiān)控又沒(méi)到位,這個(gè)時(shí)候需要一個(gè)最大內(nèi)存和查詢策略進(jìn)行兜底盯荤,保證緩存依舊可用了,直接就OOM焕盟。


三秋秤、緩存粒度控制

image.png

1. 方式

(1)緩存全部屬性:select * from table
(2)緩存部分屬性:select column1, column2... from table

2. 粒度控制的三個(gè)角度

(1)通用性:全屬性最好
(2)占用空間:部分屬性最好
(3)代碼維護(hù):表面上全屬性最好

3.思考

??真的需要緩存全量屬性嗎?有必要考慮拓展性嗎脚翘?像user表灼卢、字典表 緩存全量屬性很好,但是其他場(chǎng)景的


四来农、緩存穿透優(yōu)化

大量請(qǐng)求不命中鞋真,返回null

緩存?zhèn)鹘y(tǒng)原理圖解

1. 產(chǎn)生原因

(1)業(yè)務(wù)代碼自身問(wèn)題
(2)惡意攻擊、爬蟲(chóng)

  • eg:視頻網(wǎng)站回顯到HTML中的URL頁(yè)面的內(nèi)容加密沃于,防止爬蟲(chóng)涩咖。獲取到爬蟲(chóng)或攻擊程序調(diào)用url,但是參數(shù)加密它不知道怎么傳繁莹,此時(shí)就獲取不到數(shù)據(jù)檩互,即可能產(chǎn)生緩存穿透危害。

2. 如何發(fā)現(xiàn)

(1)業(yè)務(wù)的響應(yīng)時(shí)間
(2) 業(yè)務(wù)本身問(wèn)題
(3)監(jiān)控系統(tǒng)
(4) 相關(guān)指標(biāo):總調(diào)用數(shù)咨演、緩存層命中數(shù)闸昨、存儲(chǔ)層命中數(shù)

3. 解決方案

方案一:緩存空對(duì)象
解決方法1:緩存空對(duì)象

示例代碼:

public String getPassThrough(Map<String,String> records,String key) {
    Jedis jedis = new JedisPool().getResource();
    String cacheValue = jedis.get(key);
    if(null == cacheValue || ("").equals(cacheValue)) {
        String storageValue = records.get(key);
        if(null == storageValue || ("").equals(storageValue))
            jedis.setex(key, 5, storageValue);
        else 
            jedis.set(key, storageValue);
        
        return storageValue;
    } else {
        return cacheValue;
    }
}

兩個(gè)問(wèn)題:

  1. 產(chǎn)生大量的空值鍵
    如果產(chǎn)生了大量的 { nullKey : null } ,那么也會(huì)對(duì)Redis的訪問(wèn)產(chǎn)生影響,所以一般設(shè)置一個(gè)過(guò)期時(shí)間薄风。

  2. 緩存層和存儲(chǔ)層 “短期” 數(shù)據(jù)不一致饵较。(記得更新緩存)


方案二:布隆過(guò)濾器攔截(額外的代碼,可能引申出新問(wèn)題)

布隆過(guò)濾器


五遭赂、無(wú)底洞問(wèn)題優(yōu)化

  1. 問(wèn)題來(lái)源
    2010年facebook有3000個(gè) Memcache節(jié)點(diǎn)循诉,增加新緩存機(jī)器,性能不升反降嵌牺。
圖例打洼,耗費(fèi)更多的網(wǎng)絡(luò)龄糊,且何時(shí)返回取決于查詢最慢的節(jié)點(diǎn)
  1. 問(wèn)題關(guān)鍵點(diǎn):
    1)更多機(jī)器 不代表性能提升
    2)批量接口需求(mget、mset)
    3)數(shù)據(jù)增長(zhǎng)與水平拓展需求
  1. 優(yōu)化IO的集中方法
    1)命令本身優(yōu)化:例如慢查詢keys募疮、hgetall bigkey
    2)減少網(wǎng)絡(luò)通信次數(shù)
    3)優(yōu)化SQL
    4)降低客戶端接入成本炫惩,例如客戶端長(zhǎng)連接 、連接池阿浓、NIO等
  1. 四種優(yōu)化方法(參見(jiàn)上節(jié))
    1) 串行mget
    2)串行IO
    3)并行IO
    4)hash_tag

六他嚷、緩存雪崩優(yōu)化



七、熱點(diǎn)key重建優(yōu)化


熱點(diǎn)key重建優(yōu)化場(chǎng)景 - 大訪問(wèn)量場(chǎng)景的多線程并發(fā)重建

1. 三個(gè)方案

1)減少重緩存次數(shù)
2)數(shù)據(jù)盡可能一致
3)減少潛在危險(xiǎn)

2. 兩個(gè)解決方案

1)互斥鎖(mutex key)
互斥鎖原理圖
public String get(String key) {
    String value = jedis.get(key);
    if(value == null) {
        String mutexKey = "mutex:key:"+key;
        if(jedis.set(mutexKey,"1","ex 180","nx")) {
            value = db.get(key);
            jedis.set(key,value);
            jedis.delete(mutexKey);
        } else {
            //其它線程休息50秒后重試
            TimeUnit.SECONDS.sleep(50);
            get(key);
        }
    }
    return value;
}
2)永不過(guò)期
  1. 緩存層面:
    沒(méi)有設(shè)置過(guò)期時(shí)間(沒(méi)用expire)
  2. 功能層面:
    為每個(gè)value添加\color{blue}{邏輯過(guò)期時(shí)間(logicTimeout自己存在redis里的值)}
    當(dāng)發(fā)現(xiàn)超過(guò)邏輯過(guò)期時(shí)間后芭毙,會(huì)使用單獨(dú)的線程去構(gòu)建緩存筋蓖。
    優(yōu)點(diǎn): 相比互斥??而言,不會(huì)等待退敦,而且只有一個(gè)獨(dú)立線程去重建
    問(wèn)題: 可能存在數(shù)據(jù)不一致粘咖。重建過(guò)程進(jìn)行中,拿了老的值侈百。
永不過(guò)期圖解
public String get2(final String key) {
    V v = jedis.get(key);
    String value = v.getValue();
    long logicTimeout = v.getTimeout();
    if(logicTimeout > System.currentTimeMillis()) {
        String mutexKey = "mutex:key:"+key;
        if(jedis.set(mutexKey,"1","ex 180","nx")) {
            threadPool.execute(new Runnable() {
                @Override
                public void run() {
                    String dbValue = db.get(key);
                    jedis.set(key,dbValue);
                    jedis.delete(mutexKey);
                }
            });
        }
    }
    return value;
}
3)兩種方案對(duì)比
方案 優(yōu)點(diǎn) 缺點(diǎn)
互斥鎖 - 思路簡(jiǎn)單
- 保證一致性
- 代碼復(fù)雜度增加
- 存在\color{red}{死鎖}風(fēng)險(xiǎn)
永不過(guò)期 - 基本杜絕熱點(diǎn)key問(wèn)題 - 不保證一致性
- 邏輯過(guò)期時(shí)間增加維護(hù)成本和內(nèi)存成本
- 策略:讓logicTimeout < realTimeout瓮下,
- 策略考量:為緩存重建提供寬裕的時(shí)間


八、本章總結(jié)

? 緩存收益:加速讀寫(xiě)钝域、降低后端存儲(chǔ)負(fù)載讽坏。
? 緩存成本:緩存和存儲(chǔ)數(shù)據(jù)不一致性、代碼維護(hù)成本例证、運(yùn)維成本路呜。
? 推薦方案:結(jié)合剔除、超時(shí)织咧、主動(dòng)更新三種方案共同完成胀葱。
? 穿透問(wèn)題:使用緩存空對(duì)象和布隆過(guò)濾器來(lái)解決,注意它們各自的使用場(chǎng)
景和局限性笙蒙。
? 無(wú)底洞問(wèn)題:分布式緩存中巡社,有更多的機(jī)器不保證有更高的性能。
有四種 批量操作方式:串行命令手趣、串行10晌该、并行1〇、hashjag绿渣。
? 雪崩問(wèn)題:緩存層高可用朝群、客戶端降級(jí)、提前演練是解決雪崩問(wèn)題的重要
方法中符。
? 熱點(diǎn)key問(wèn)題:互斥鎖姜胖、"7卞遠(yuǎn)不過(guò)期"能夠在一定程度上解決熱點(diǎn)key問(wèn)
題,開(kāi)發(fā)人員在使用時(shí)要了解它們各自的使用成本淀散。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末右莱,一起剝皮案震驚了整個(gè)濱河市蚜锨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌慢蜓,老刑警劉巖亚再,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異晨抡,居然都是意外死亡氛悬,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)耘柱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)如捅,“玉大人,你說(shuō)我怎么就攤上這事调煎【登玻” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵士袄,是天一觀的道長(zhǎng)烈涮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)窖剑,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任戈稿,我火速辦了婚禮西土,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鞍盗。我一直安慰自己需了,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布般甲。 她就那樣靜靜地躺著肋乍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪敷存。 梳的紋絲不亂的頭發(fā)上墓造,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音锚烦,去河邊找鬼觅闽。 笑死,一個(gè)胖子當(dāng)著我的面吹牛涮俄,可吹牛的內(nèi)容都是我干的蛉拙。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼彻亲,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼孕锄!你這毒婦竟也來(lái)了吮廉?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤畸肆,失蹤者是張志新(化名)和其女友劉穎宦芦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體恼除,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡踪旷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豁辉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片令野。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖徽级,靈堂內(nèi)的尸體忽然破棺而出气破,到底是詐尸還是另有隱情,我是刑警寧澤餐抢,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布现使,位于F島的核電站,受9級(jí)特大地震影響旷痕,放射性物質(zhì)發(fā)生泄漏碳锈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一欺抗、第九天 我趴在偏房一處隱蔽的房頂上張望售碳。 院中可真熱鬧,春花似錦绞呈、人聲如沸贸人。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至圾亏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間父晶,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工弄跌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甲喝,地道東北人铛只。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓糠溜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親直撤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子非竿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,105評(píng)論 1 32
  • 轉(zhuǎn) # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    呂品?閱讀 9,732評(píng)論 0 44
  • --- layout: post title: "如果有人問(wèn)你關(guān)系型數(shù)據(jù)庫(kù)的原理谋竖,叫他看這篇文章(轉(zhuǎn))" date...
    藍(lán)墜星閱讀 793評(píng)論 0 3
  • 今天看到一位朋友寫(xiě)的mysql筆記總結(jié),覺(jué)得寫(xiě)的很詳細(xì)很用心蓖乘,這里轉(zhuǎn)載一下,供大家參考下零聚,也希望大家能關(guān)注他原文地...
    信仰與初衷閱讀 4,734評(píng)論 0 30
  • 在游子的心中些侍, 除去飽覽千山萬(wàn)水的胸懷隶症, 還有一個(gè)遠(yuǎn)方岗宣, 是故鄉(xiāng)。 我的遠(yuǎn)方耗式, 沒(méi)有霓虹燈, 但有乳白色的月光, ...
    寧筱閱讀 1,081評(píng)論 6 7